ellelstone / elles_icc_profiles

Elle Stone's Well-Behaved ICC Profiles and Code
http://ninedegreesbelow.com/photography/lcms-make-icc-profiles.html
Other
101 stars 15 forks source link

Is it possible to 'fix' a profile created with dcamprof that isn't well behaved? #4

Open abnormally-distributed opened 3 years ago

abnormally-distributed commented 3 years ago

I don't know how else to contact the author of this package so I am posing a question here:

with dcamprof I seem unable to achieve a well behaved working profile. For example, xicclu will return lab values such as "99.999410 -0.000094 0.000216" when feeding it 255,255,255 RGB values. Or, if having it return xyz coordinates, 0.964188, 0.999985, 0.824890. This is off from the white point by x=1.1999e-05 , y=1.5000e-05, z=9.9980e-06 . This seems almost surely a hexadecimal issue. The gamma in my profile is a simple linear gamma (parametric, not a point linear approximation).

Is it feasible to use this software to fix the profile, or is there perhaps another solution available if not?

ellelstone commented 3 years ago

Hello @abnormally-distributed

https://github.com/Beep6581/dcamprof says that dcamprof depends on LCMS. LCMS does not - or didn't last I checked and probably still doesn't - include any code for dealing with hexadecimal rounding. So unless decamprof includes extra code for dealing with LCMS deficiency, decamprof also will fail to account for hexadecimal rounding.

To make my well-behaved profiles I modified ArgyllCMS source code and used a spreadsheet to produce "prequantified" primaries to feed to LCMS, in order to make V2 and V4 ICC profiles using LCMS, that have colorants that match profiles distributed by ArgyllCMS. Which I'm guessing you already know: https://ninedegreesbelow.com/photography/well-behaved-profiles-quest.html#hexadecimal-quantization https://ninedegreesbelow.com/photography/lcms-make-icc-profiles.html

I posted the quantization issue to the LCMS mailing list back in 2014, but never got a response. See the bottom of this page: https://sourceforge.net/p/lcms/mailman/lcms-user/?viewmonth=201402&limit=100

On a somewhat related note, if you peruse from the top of the page, you'll also see a long discussion of how LCMS code uses (or used, haven't checked back for several years) the wrong white point for D65 ICC profiles, which issue also wasn't fixed then, and I;m guessing still hasn't been fixed. See: https://ninedegreesbelow.com/photography/linux-icc-profiles.html#variants

So if LCMS and/or dcamprof haven't fixed their hexadecimal point issue, then you are out of luck. If you can code, then you might consider writing a patch following ArgyllCMS code, for submitting to dcamprof and/or to LCMS, and then try to get your patch accepted into the code base, or else at least modify decamprof or LCMS for your own use and hopefully share your patch online.

If somehow you already know the correct unadapted primaries for your profiles, you can modify ArgyllCMS code (I think just one file but it's been years since I've done this), and recompile and run, and use the resulting profile's profile colorants and a spreadsheet to get "prequantized primaries" to feed to LCMS to make a V4 profile. That's how I made my well-behaved profiles. The spreadsheet attached to this article contains all the required equations: https://ninedegreesbelow.com/photography/srgb-color-space-to-profile.html

Above assumes you want a V4 profile instead of the V2 profile made by ArgyllCMS, and also assumes ArgyllCMS doesn't yet make V4 profiles - it's been awhile since I checked the status of V4 profiles in ArgyllCMS code.

I can't think of any way to fix a dcamprof-produced profile if you don't have the actual primaries and white point from which the decamprof profile was made. I don't think the information in a V4 profile is sufficiently accurate to work backwards and then forwards again.

The failure to properly prequantize when making a profile still produces profiles that are close enough to well-behaved that in practice it would only make a visible difference in images with white and nearly white tonalities that have been converted from camera space to a working space and then subjected to fairly extreme edits involving adding saturation. Have you noticed a problem in practice as opposed to a problem "by the numbers"? Best regards, Elle

abnormally-distributed commented 3 years ago

Thank you for getting back to me! I haven't noticed any issues, but then again, maybe I don't recognize them because incorrect profiles are what I am familiar with.

The dcamprof profile is made with a D50 white point, so I would think the unadapted primaries are just the same.

abnormally-distributed commented 3 years ago

I actually figured out a solution! I took the row sums of the dcamprof matrix, and took your white point values (0.96420288, 1.0, 0.82490540) and divided them to get weights using the R package Rmpfr to use a larger degree of precision than R offers on its own. I used 128 bit precision but that is probably severe overkill. Anyway, I then multiplied each row of the matrix by the corresponding weight to ensure that they sum to the correct white point. The function mpfr converts objects to the format needed for extra precision.

Then I opened the profile in Lumariver profile designer (but a tool that can convert it to xml would probably work fine too), pasted in the new matrix and white point, loaded it into xicclu and tested it and it is now well behaved!

R code syntax:

library(Rmpfr)
sony <- rbind(  c(  0.803802,  0.147522,  0.012863 ),c(  0.222687,  0.758392,  0.018921 ), c(  0.019150,  0.016647,  0.789093 ))) # this is the matrix from the dcamprof profile for my camera
wp <- mpfr(c(0.96420288, 1.0, 0.82490540), 128) # white point, storing it as an mpfr object allows the following calculations to use the higher precision
wts <- wp/rowSums(sony) #The weights representing how much bigger the wp values are compared to the rowsums of the forward matrix
sony * wts #prints the new matrix to the console , from here I copy and paste this along with the white point into lumariver