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

Reply via email to