Hi Elle, This is a nice finding. I have to double check the implications, but for what it seems you are proposing a value for D50 that minimizes the rounding errors on some circumstances.
> So what happens if the D50 XYZ values in lcms2.h are changed to match > the iccToXml illuminant values? XYZ numbers are stored in s15.16 fixed point, so, doing a quick roundtrip test I get: cmsS15Fixed16Number xe = _cmsDoubleTo15Fixed16(cmsD50X); cmsS15Fixed16Number ye = _cmsDoubleTo15Fixed16(cmsD50Y); cmsS15Fixed16Number ze = _cmsDoubleTo15Fixed16(cmsD50Z); cmsFloat64Number x = _cms15Fixed16toDouble(xe); cmsFloat64Number y = _cms15Fixed16toDouble(ye); cmsFloat64Number z = _cms15Fixed16toDouble(ze); double dx = fabs(cmsD50X - x); double dy = fabs(cmsD50Y - y); double dz = fabs(cmsD50Z - z); printf("dX, dY, dZ = (%f %f %f)\n", dx, dy, dz); Which results in: dX, dY, dZ = (0.000003 0.000000 0.000005) Doing same with the values you propose 0.96420288, 1.0, 0.82490540 results in a perfect round trip of dx=dy=dz=0 Unfortunately I cannot change such numbers because the PCSXYZ values are defined in the ICC spec in many places, table D.5 for example. But I can bring this discussion to the ICC, and see if they see value in changing the constants. Anyway, keep in mind this only applies on matrix-shaper profiles, which are a *very reduced* subset of all available profile types. On LUT-based output profiles, using those values may probably make little difference, and since D50 is used to normalize the PCS may have other side effects. Also, giving 0.000000 or 0.000005 is a pure cosmetic question, since this is far below the noticeable difference. Regards Marti Quoting Elle Stone <l.elle.st...@gmail.com>: > While creating profiles using different profile white points, I > noticed a pattern that suggests a rounding error. For example, running > the command "xicclu -ir -pl -s255 profile.icc" on the following 7 > profiles produces these results: > > Apple-CCT 100.000000 -0.002638 0.000000 > Apple-D65code 100.000000 0.000000 0.000000 perfect > > CIE-RGB-CCT 100.000000 0.000000 0.001233 > CIE-RGB-E_5454K 100.000000 0.000000 0.001233 > > Clay-CCT 100.000000 -0.002638 0.001233 > Clay-D65_old 100.000000 0.000000 0.001233 > > NTSC-CCT 100.000000 0.000000 0.001233 > NTSC-C_6774K 100.000000 0.000000 0.001233 > > SMPTE-CCT 100.000000 0.000000 -0.001233 > SMPTE-D65_old 100.000000 -0.002638 0.001233 > > sRGB-CCT 99.999410 0.002543 -0.001017 > sRGB-D65code 100.000000 0.000000 0.001233 > > Widegamut-CCT 100.000590 -0.005181 0.001017 > Widegamut-D50_lcms 100.000000 0.000000 0.001233 > > Profile white point key: > "CCT" = lcms correlated color temp; I used 6503.6 for D65. > D65code = (0.31271, 0.32912) > E_5454K = (0.333608970, 0.348572909) Robertson equations > D65_old = (0.312700, 0.329000) > C_6774K = (0.308548930, 0.324928102) Robertson equations > D50_lcms = (0.345702915, 0.358538597) > > In the profiles above, the value +/- 0.001233 shows up ten times over > a diverse set of profile white points. Including results from other > profiles, 0.002543, 0.001017 and 0.002638 also show up multiple times, > though not as frequently as 0.001233. > > For R=G=B=255, no deviation from 0 in the Lab "a" channel plus a > deviation of 0.001233 in the Lab "b" channel corresponds to a > deviation of 0.000015 (+0.001233) or 0.000016 (-0.001233) in the Z XYZ > channel (the X value deviation is 0 in either case). The values > "0.000015" and "0.000016" are important numbers when converting from > XYZ to hexadecimal: > > 0.000015 (and any smaller value), multiplied by 65535 and converted to > hex, is 0. > 0.000016, multiplied by 65535 and converted to hex, is 1. > > This might be purely coincidental, but it suggests a decimal to > hexadecimal rounding error. So I looked for a possible source of a "1 > hex unit" error and perhaps found one. The following lines are in the > "lcms2.h" file: > > // D50 XYZ normalized to Y=1.0 > #define cmsD50X 0.9642 > #define cmsD50Y 1.0 > #define cmsD50Z 0.8249 > > Using these cmsD50X and cmsD50Z values, here's the round-trip > conversion through hex: > > starting values: (0.964200000, 1.0, 0.824900000) > convert to hex: (F6D4, FFFF, D32B) > convert back to decimal: (0.964187076, 1.0, 0.824887465) > absolute difference: (0.000012924, 0.0, 0.000012535) > > According to iccToXml, for profiles generated by lcms the profile > header illuminant value is (0.964202881, 1, 0.824905396). The > corresponding round-trip conversion through hex values are: > > starting values: (0.964202881, 1.0, 0.824905396) > convert to hex: (F6D5, FFFF, D32C) > convert back to decimal: (0.824902724, 1.0, 0.964202335) > absolute difference: (0.000000546, 0.0, 0.000002672) > > Notice that the iccToXml illuminant values convert to hex and back > with a smaller error, and also the resulting hex values are larger by > 1 hex unit (F6D4->F6D5, D32B->D32C). > > So what happens if the D50 XYZ values in lcms2.h are changed to match > the iccToXml illuminant values? > > // D50 XYZ normalized to Y=1.0 > #define cmsD50X 0.96420288 //iccToXml header illuminant value > #define cmsD50Y 1.0 > #define cmsD50Z 0.82490540 //iccToXml header illuminant value > > To find out, I > *Changed the D50 values in lcms2.h to equal the header illuminant > value reported by iccToXml > *Recompiled lcms > *Recompiled my profile-making code > *Recreated all the profiles using the exact same white points as before > > Here are the new xicclu results: > > Apple-mod-CCT 100.000000 0.002638 0.000000 flipped sign > Apple-mod-D65code 100.000000 0.000000 0.000000 perfect > > CIE-RGB-mod-CCT 100.000000 0.000000 0.000000 perfect > CIE-mod-RGB-E_5454 100.000000 0.000000 0.000000 perfect > > Clay-mod-CCT 100.000000 0.000000 0.001233 improved > Clay-mod-D65_old 100.000000 0.000000 0.000000 perfect > > NTSC-mod-CCT 100.000000 0.000000 0.000000 perfect > NTSC-mod-C_6774 100.000000 0.000000 0.000000 perfect > > SMPTE-mod-CCT 100.000000 0.000000 -0.001233 no change > SMPTE-mod-D65_old 100.000000 0.000000 0.000000 perfect > > sRGB-mod-CCT 99.999410 0.002543 -0.001017 no change > sRGB-mod-D65code 100.000000 0.000000 0.000000 perfect > > Widegamut-mod-CCT 100.000590 -0.005181 0.001017 no change > Widegamut-mod-D50_lcms 100.000000 0.000000 0.000000 perfect > > I've checked many more profiles than are listed above, and the results > are 100% consistent. > > "Color balanced" isn't everything! I checked all the profiles against > the Lindbloom xyY values by calculating the sum of the absolute > differences in the x,y,Y values for the red, blue, and green channels. > In most cases, the profiles produced by the modified lcms2.h file are > slightly closer to the Lindbloom values than the profiles produced by > the unmodified lcms2.h file. Widegamut and CIE-RGB values are slightly > farther away. In all cases the change is very small. > > So if you actually had the patience to read all the way through this > post, does it look like there might be something in the lcms source > code that is systematically introducing small rounding errors that are > independent of the profile white point? > > Elle ------------------------------------------------------------------------------ Learn the latest--Visual Studio 2012, SharePoint 2013, SQL 2012, more! Discover the easy way to master current and previous Microsoft technologies and advance your career. Get an incredible 1,500+ hours of step-by-step tutorial videos with LearnDevNow. Subscribe today and save! http://pubads.g.doubleclick.net/gampad/clk?id=58040911&iu=/4140/ostg.clktrk _______________________________________________ Lcms-user mailing list Lcms-user@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/lcms-user