Thread: [Lcms-user] Bug? conversion value discrepencies if the destination profile is built-in vs on disk
An ICC-based CMM for color management
Brought to you by:
mm2
|
From: Elle S. <ell...@ni...> - 2014-04-02 17:18:13
|
There are discrepancies when converting to an lcms built-in profile,
compared to converting to the same profile previously saved to disk.
I noticed the discrepancies while testing GIMP 2.9 16-bit integer and
32-bit floating point ICC profile conversions. The same discrepancies
happen when using tificc and also when using transicc. So the
discrepancies seems to be consistent across various ways of accessing
lcms built-in profiles.
Here is transicc output showing the discrepancies:
Converting to a copy of the lcms built-in sRGB profile that was
previously saved to disk ("-o sRGB-lcms-built-in.icc"):
$ transicc -w -t1 -c0 -b -i sRGB-elle-V4-g100.icc -o sRGB-lcms-built-in.icc
LittleCMS ColorSpace conversion calculator - 4.2 [LittleCMS 2.06]
Enter values, 'q' to quit
R? 255 255 255
G? B?
R=255.0019 G=254.9968 B=255.0028
Enter values, 'q' to quit
R? 255 0 0
G? B?
R=255.0450 G=0.0839 B=-0.0372
Enter values, 'q' to quit
R? 0 255 0
G? B?
R=-1.3516 G=254.9937 B=-0.3004
Enter values, 'q' to quit
R? 0 0 255
G? B?
R=0.0858 G=0.0080 B=255.0143
Converting to the transicc built-in sRGB profile ("-o *sRGB"):
$ transicc -w -t1 -c0 -b -i sRGB-elle-V4-g100.icc -o *sRGB
LittleCMS ColorSpace conversion calculator - 4.2 [LittleCMS 2.06]
Enter values, 'q' to quit
R? 255 255 255
G? B?
R=255.0007 G=254.9997 B=255.0009
Enter values, 'q' to quit
R? 255 0 0
G? B?
R=255.0428 G=0.1139 B=-0.0725
Enter values, 'q' to quit
R? 0 255 0
G? B?
R=-1.3259 G=254.9944 B=-0.2851
Enter values, 'q' to quit
R? 0 0 255
G? B?
R=0.0893 G=0.0423 B=255.0130
Here's the code that I used to save a copy of the lcms built-in sRGB
profile to disk:
After declaring/defining the variables:
profile = cmsCreate_sRGBProfile();
cmsWriteTag(profile, cmsSigCopyrightTag, copyright);
cmsWriteTag(profile, cmsSigDeviceMfgDescTag, manufacturer);
description = cmsMLUalloc(NULL, 1);
cmsMLUsetASCII(description, "en", "US", "sRGB-lcms-built-in.icc.");
cmsWriteTag(profile, cmsSigProfileDescriptionTag, description);
filename = "sRGB-lcms-built-in.icc";
cmsSaveProfileToFile(profile, filename);
cmsMLUfree(description);
Elle Stone
|
|
From: <Mar...@li...> - 2014-04-02 20:44:14
|
Hi,
The ICC file format stores matrix of sRGB as 15.16 fixed point, that
means the precision you have is 1 / ((1 << 16) - 1) which is
about 1.5e-5 Since evaluating the matrix implies multiplication
and addition, the final precision is reduced to 1e-3, that means
only two decimal places are accurate. This is not a major problem
because is far below 1 dE.
The in-memory built-in is not quantized and does not have this
problem, as soon as you serialize it, you got quantization.
So, that is because the XYZ representation of file format. You
may want to use LUT based profiles instead.
Regards
Marti
Quoting Elle Stone <ell...@ni...>:
> There are discrepancies when converting to an lcms built-in profile,
> compared to converting to the same profile previously saved to disk.
>
> I noticed the discrepancies while testing GIMP 2.9 16-bit integer and
> 32-bit floating point ICC profile conversions. The same discrepancies
> happen when using tificc and also when using transicc. So the
> discrepancies seems to be consistent across various ways of accessing
> lcms built-in profiles.
>
> Here is transicc output showing the discrepancies:
>
> Converting to a copy of the lcms built-in sRGB profile that was
> previously saved to disk ("-o sRGB-lcms-built-in.icc"):
>
> $ transicc -w -t1 -c0 -b -i sRGB-elle-V4-g100.icc -o sRGB-lcms-built-in.icc
> LittleCMS ColorSpace conversion calculator - 4.2 [LittleCMS 2.06]
>
> Enter values, 'q' to quit
> R? 255 255 255
> G? B?
> R=255.0019 G=254.9968 B=255.0028
>
> Enter values, 'q' to quit
> R? 255 0 0
> G? B?
> R=255.0450 G=0.0839 B=-0.0372
>
> Enter values, 'q' to quit
> R? 0 255 0
> G? B?
> R=-1.3516 G=254.9937 B=-0.3004
>
> Enter values, 'q' to quit
> R? 0 0 255
> G? B?
> R=0.0858 G=0.0080 B=255.0143
>
> Converting to the transicc built-in sRGB profile ("-o *sRGB"):
>
> $ transicc -w -t1 -c0 -b -i sRGB-elle-V4-g100.icc -o *sRGB
> LittleCMS ColorSpace conversion calculator - 4.2 [LittleCMS 2.06]
>
> Enter values, 'q' to quit
> R? 255 255 255
> G? B?
> R=255.0007 G=254.9997 B=255.0009
>
> Enter values, 'q' to quit
> R? 255 0 0
> G? B?
> R=255.0428 G=0.1139 B=-0.0725
>
> Enter values, 'q' to quit
> R? 0 255 0
> G? B?
> R=-1.3259 G=254.9944 B=-0.2851
>
> Enter values, 'q' to quit
> R? 0 0 255
> G? B?
> R=0.0893 G=0.0423 B=255.0130
>
>
> Here's the code that I used to save a copy of the lcms built-in sRGB
> profile to disk:
>
> After declaring/defining the variables:
>
> profile = cmsCreate_sRGBProfile();
> cmsWriteTag(profile, cmsSigCopyrightTag, copyright);
> cmsWriteTag(profile, cmsSigDeviceMfgDescTag, manufacturer);
> description = cmsMLUalloc(NULL, 1);
> cmsMLUsetASCII(description, "en", "US", "sRGB-lcms-built-in.icc.");
> cmsWriteTag(profile, cmsSigProfileDescriptionTag, description);
> filename = "sRGB-lcms-built-in.icc";
> cmsSaveProfileToFile(profile, filename);
> cmsMLUfree(description);
>
>
> Elle Stone
>
> ------------------------------------------------------------------------------
> _______________________________________________
> Lcms-user mailing list
> Lcm...@li...
> https://lists.sourceforge.net/lists/listinfo/lcms-user
|
|
From: Elle S. <ell...@ni...> - 2014-04-03 12:29:05
|
On 04/02/2014 04:43 PM, Mar...@li... wrote: > > > Hi, > > The ICC file format stores matrix of sRGB as 15.16 fixed point, that > means the precision you have is 1 / ((1 << 16) - 1) which is > about 1.5e-5 Since evaluating the matrix implies multiplication > and addition, the final precision is reduced to 1e-3, that means > only two decimal places are accurate. This is not a major problem > because is far below 1 dE. > Hi Marti, My apologies, I didn't understand all of what you said. Are you saying that conversions to sRGB are only accurate to two decimal places, meaning somewhat less than five significant digits in terms of floating point precision? Previously I tested 32-bit floating point round-trip conversions from ProPhotoRGB to sRGB and back using your wonderful unbounded mode ICC profile conversions. The round trip conversion (using only profiles from disk and involving 4 sequential ICC profile conversions) is 100% lossless: http://ninedegreesbelow.com/photography/lcms2-unbounded-mode.html#pro2srgb I would have expected rounding errors during the unbounded mode round trip conversions if the conversions were accurate only to two decimal places. How is the round-trip conversion lossless despite only two decimal places of accuracy? My ability to visualize/grasp the math fails at this point. > > The in-memory built-in is not quantized and does not have this > problem, as soon as you serialize it, you got quantization. > Are you saying the conversion to the built-in profile that was created and stored in memory is more accurate? or less accurate? than the conversion to the same profile that's been saved to disk? It seems to me that it's less accurate. Here's another example of transicc output with less confusing RGB values. In this case transicc converts from a linear gamma version of the lcms built-in sRGB (cmsCreate_sRGBProfile) that had been created and saved to disk. When converting from linear to regular sRGB (both profiles using the same primaries and white point), the resulting output RGB values should match the source RGB values for all source values like (0,0,0), (255,255,255), (255,0,0), etc. Converting to the built-in lcms sRGB profile that had been created and saved to disk: $ transicc -w -c0 -b -t1 -i sRGB-lcms-primaries-wtpt-V4-g100.icc -o sRGB-lcms-primaries-wtpt-V4-srgbtrc.icc 255 255 255 R=255.0000 G=255.0000 B=255.0000 255 0 0 R=255.0000 G=0.0000 B=-0.0000 0 255 0 R=-0.0002 G=255.0000 B=-0.0000 0 0 255 R=-0.0001 G=0.0000 B=255.0000 The figures above are accurate to almost 4 decimal places. Converting to the lcms built-in sRGB profile: $ transicc -w -c0 -b -t1 -i sRGB-lcms-primaries-wtpt-V4-g100.icc -o *sRGB 255 255 255 R=254.9988 G=255.0029 B=254.9981 0 255 0 R=0.0254 G=255.0008 B=0.0153 0 0 255 R=0.0034 G=0.0343 B=254.9988 The figures above are accurate to 2 decimal places. So it looks to me like conversions to the profile that had been saved to disk are more accurate. GIMP from git does 32-bit unbounded mode floating point conversions from the source color space profile (which may be a linear gamma color space) to sRGB (and possibly to linear gamma sRGB), keeping the out-of-gamut RGB values rather than clipping them. So the conversions do need to be accurate. Can I modify the GIMP ICC profile conversion code to make conversions to the GIMP built-in sRGB *exactly* match conversions to the same profile that has been saved to disk? Perhaps there is an optimization switch that needs to be set or unset? Or is the only alternative rewriting the GIMP code to save the built-in profile to disk and then convert to the disk copy instead of to the copy in memory? > So, that is because the XYZ representation of file format. You > may want to use LUT based profiles instead. > This possible sRGB LUT profile, is there one that can be made with LCMS? Can it be used for unbounded mode ICC profile conversions? When converting to the LUT profile in memory, will the accuracy be better than or at least as good as the accuracy when converting to a matrix sRGB profile from disk? > Regards > Marti > Best regards, Elle |
|
From: <Mar...@li...> - 2014-04-03 15:59:20
|
Hi Elle, Sorry I didn't explain myself. I mean, when you actually store a built-in profile to disk, you are forced to use the ICC profile format. The ICC profile format has some limitations when storing floating point numbers. That means, if you have a floating point number in memory that is, say, 1.234567890, the file format used by ICC stores it as 1.23457. Then, when you read the profile again, the number you obtain is 1.23457 which has only 5 decimal places of precision and is slightly different from the original number. In your example you were mixing a yet existing profile with the srgb builtin and the builtin saved to disk. So, if you save the builtin to disk and read it again, you actually get slightly different numbers. If those numbers are the 3x3 matrix elements, you got different results. As a proof of that, if you save the builtin and you use the saved file as input and output, it still roundtrips well. transicc -i sRGB_builtin.icc -o sRGB_builtin.icc LittleCMS ColorSpace conversion calculator - 4.2 [LittleCMS 2.06] Enter values, 'q' to quit R? 255 G? 255 B? 255 R=255.0000 G=255.0000 B=255.0000 etc. So, this loss of precision is due to the file format. Hope it makes sense to you Regards Marti Quoting Elle Stone <ell...@ni...>: > On 04/02/2014 04:43 PM, Mar...@li... wrote: >> >> >> Hi, >> >> The ICC file format stores matrix of sRGB as 15.16 fixed point, that >> means the precision you have is 1 / ((1 << 16) - 1) which is >> about 1.5e-5 Since evaluating the matrix implies multiplication >> and addition, the final precision is reduced to 1e-3, that means >> only two decimal places are accurate. This is not a major problem >> because is far below 1 dE. >> > > Hi Marti, > > My apologies, I didn't understand all of what you said. Are you saying > that conversions to sRGB are only accurate to two decimal places, > meaning somewhat less than five significant digits in terms of floating > point precision? > > Previously I tested 32-bit floating point round-trip conversions from > ProPhotoRGB to sRGB and back using your wonderful unbounded mode ICC > profile conversions. The round trip conversion (using only profiles from > disk and involving 4 sequential ICC profile conversions) is 100% lossless: > http://ninedegreesbelow.com/photography/lcms2-unbounded-mode.html#pro2srgb > > I would have expected rounding errors during the unbounded mode round > trip conversions if the conversions were accurate only to two decimal > places. How is the round-trip conversion lossless despite only two > decimal places of accuracy? My ability to visualize/grasp the math fails > at this point. > > > > > The in-memory built-in is not quantized and does not have this > > problem, as soon as you serialize it, you got quantization. > > > > Are you saying the conversion to the built-in profile that was created > and stored in memory is more accurate? or less accurate? than the > conversion to the same profile that's been saved to disk? It seems to me > that it's less accurate. > > Here's another example of transicc output with less confusing RGB > values. In this case transicc converts from a linear gamma version of > the lcms built-in sRGB (cmsCreate_sRGBProfile) that had been created and > saved to disk. > > When converting from linear to regular sRGB (both profiles using the > same primaries and white point), the resulting output RGB values should > match the source RGB values for all source values like (0,0,0), > (255,255,255), (255,0,0), etc. > > Converting to the built-in lcms sRGB profile that had been created and > saved to disk: > > $ transicc -w -c0 -b -t1 -i sRGB-lcms-primaries-wtpt-V4-g100.icc -o > sRGB-lcms-primaries-wtpt-V4-srgbtrc.icc > > 255 255 255 > R=255.0000 G=255.0000 B=255.0000 > > 255 0 0 > R=255.0000 G=0.0000 B=-0.0000 > > 0 255 0 > R=-0.0002 G=255.0000 B=-0.0000 > > 0 0 255 > R=-0.0001 G=0.0000 B=255.0000 > > The figures above are accurate to almost 4 decimal places. > > > Converting to the lcms built-in sRGB profile: > > $ transicc -w -c0 -b -t1 -i sRGB-lcms-primaries-wtpt-V4-g100.icc -o *sRGB > 255 255 255 > R=254.9988 G=255.0029 B=254.9981 > > 0 255 0 > R=0.0254 G=255.0008 B=0.0153 > > 0 0 255 > R=0.0034 G=0.0343 B=254.9988 > > The figures above are accurate to 2 decimal places. > > So it looks to me like conversions to the profile that had been saved to > disk are more accurate. > > > GIMP from git does 32-bit unbounded mode floating point conversions from > the source color space profile (which may be a linear gamma color space) > to sRGB (and possibly to linear gamma sRGB), keeping the out-of-gamut > RGB values rather than clipping them. So the conversions do need to be > accurate. > > Can I modify the GIMP ICC profile conversion code to make conversions to > the GIMP built-in sRGB *exactly* match conversions to the same profile > that has been saved to disk? Perhaps there is an optimization switch > that needs to be set or unset? > > Or is the only alternative rewriting the GIMP code to save the built-in > profile to disk and then convert to the disk copy instead of to the copy > in memory? > > > >> So, that is because the XYZ representation of file format. You >> may want to use LUT based profiles instead. >> > > This possible sRGB LUT profile, is there one that can be made with LCMS? > Can it be used for unbounded mode ICC profile conversions? When > converting to the LUT profile in memory, will the accuracy be better > than or at least as good as the accuracy when converting to a matrix > sRGB profile from disk? > >> Regards >> Marti >> > > Best regards, > Elle > > > > ------------------------------------------------------------------------------ > _______________________________________________ > Lcms-user mailing list > Lcm...@li... > https://lists.sourceforge.net/lists/listinfo/lcms-user |
|
From: Elle S. <ell...@ni...> - 2014-04-04 14:19:44
|
On 04/03/2014 11:58 AM, Mar...@li... wrote: > > > > Hi Elle, > > Sorry I didn't explain myself. I mean, when you actually > store a built-in profile to disk, you are forced to use > the ICC profile format. The ICC profile format has some > limitations when storing floating point numbers. > That means, if you have a floating point number > in memory that is, say, 1.234567890, the file format > used by ICC stores it as 1.23457. Then, when you read > the profile again, the number you obtain is 1.23457 which > has only 5 decimal places of precision and is slightly > different from the original number. In your example > you were mixing a yet existing profile with the srgb > builtin and the builtin saved to disk. > > So, if you save the builtin to disk and read it again, you > actually get slightly different numbers. If those numbers are > the 3x3 matrix elements, you got different results. > > As a proof of that, if you save the builtin and you use > the saved file as input and output, it still roundtrips > well. > > transicc -i sRGB_builtin.icc -o sRGB_builtin.icc > LittleCMS ColorSpace conversion calculator - 4.2 [LittleCMS 2.06] > > Enter values, 'q' to quit > R? 255 > G? 255 > B? 255 > > R=255.0000 G=255.0000 B=255.0000 > > etc. > > So, this loss of precision is due to the file format. > > Hope it makes sense to you > Regards > Marti Hi Marti, Yes, thanks! it's beginning to make sense. If I understand you correctly, it's a matter of precision vs accuracy, defined as follows: Accuracy: the accuracy with which LCMS calculates the resulting RGB values when converting from one RGB matrix profile to another. Precision: the number of decimal places in the profile primaries used to calculate the resulting RGB values when converting from one RGB matrix profile to another. Two cases: 1. Converting from a profile on disk to a copy of the LCMS built-in sRGB profile that was previously saved to disk. 2. Converting from a profile on disk to to the LCMS built-in sRGB profile in memory. In both cases the accuracy of the conversion is the same, yes? In case 1, both profiles have primaries expressed using the same precision, quoting what you said earlier, "15.16 fixed point, that means the precision you have is 1 / ((1 << 16) - 1) which is about 1.5e-5". In case 2: * the profile on disk has primaries expressed using the precision defined by "15.16 fixed point, that means the precision you have is 1 / ((1 << 16) - 1) which is about 1.5e-5". * The profile created and held in memory has primaries expressed using a much higher precision. So the two profiles, the built-in profile saved to disk and the "same" profile held in memory, really aren't the exact same profile because the primaries are different, just as, for example, 1.5523 is different from 1.552329578. As a consequence, converting the color white, R=G=B=255, *from* a copy of the LCMS built-in sRGB profile profile that had been saved to disk *to* the LCMS built-in sRGB profile created and held in memory, is really converting to a different profile: transicc -w -c0 -b -t1 -i sRGB-lcms-built-in.icc -o *sRGB LittleCMS ColorSpace conversion calculator - 4.2 [LittleCMS 2.06] Enter values, 'q' to quit R? 255 255 255 G? B? R=254.9988 G=255.0029 B=254.9981 Enter values, 'q' to quit R? This isn't a consequence of more or less accuracy used during the conversion. LCMS performs conversions to a profile created and held in memory with the same degree of accuracy as it does when converting between two profiles on disk, yes? Rather this is a result of more and less precision. Different precision means different destination profiles, which means different conversion results. Is this a correct description of why there are discrepancies between converting to a copy of the LCMS built-in sRGB on disk vs converting to the LCMS built-in sRGB created and held in memory? Kind regards, Elle |
|
From: Elle S. <ell...@ni...> - 2014-04-07 16:17:11
|
My apologies for asking again about this issue. Different results obtain from converting to a built-in profile in memory vs "the same" profile save to disk. Is it accurate to say that the results are different because the added precision in the profile in memory means the profile in memory really isn't the same profile. A consequence of this situation is that pure white in the image on disk will become slightly off white after being converted to the built-in profile, even if the embedded profile and the built-in profile are nominally "the same", because really they aren't the same: > transicc -w -c0 -b -t1 -i sRGB-lcms-built-in.icc -o *sRGB > R? G? B? 255 255 255 > R=254.9988 G=255.0029 B=254.9981 If one wants to preserve white when converting from the profile on disk to the "same" profile in memory, is there a way to tell the built-in profile in memory to *not* use the extra precision? Thanks in advance, Elle |
|
From: Kai-Uwe B. <ku...@gm...> - 2014-04-08 03:37:35
|
Am 07.04.2014 18:17, schrieb Elle Stone: > Different results obtain from converting to a built-in profile in memory > vs "the same" profile save to disk. > > Is it accurate to say that the results are different because the added > precision in the profile in memory means the profile in memory really > isn't the same profile. ICC profiles may contain a hash value sometimes called a ID. That is computed out of nearly all content of the profile including all colorimetric tags. In order to create a profile precisely representing your above mentioned lcms build-in, in memory profiles, different tag types would be needed to represent the higher precission. That would in effect mean that the ID of such profile would be different than what can now be written to disk. Hence the profiles are different by that definition. Caching of profiles and transforms depend on the ID in order to work relyable. So there is prectical use in this information. > A consequence of this situation is that pure white in the image on disk > will become slightly off white after being converted to the built-in > profile, even if the embedded profile and the built-in profile are > nominally "the same", because really they aren't the same: > >> transicc -w -c0 -b -t1 -i sRGB-lcms-built-in.icc -o *sRGB >> R? G? B? 255 255 255 >> R=254.9988 G=255.0029 B=254.9981 Correct round tripping was at some point an argument to implement non ICC colour matching engines. So I guess your point is spot on for some users. > If one wants to preserve white when converting from the profile on disk > to the "same" profile in memory, is there a way to tell the built-in > profile in memory to *not* use the extra precision? As a side note, correct round tripping became possible with the introduction of the mpet tag type. However mpet tags are only optional substitutes for A2Bx and B2Ax tags. So they can not be used for matrix shaper profiles. The later are the ones written by lcms for the build-in profiles you examined. If matrix shaper profiles could use a XYZ tag type with floating point precission your issue would be gone. kind regards Kai-Uwe -- www.behrmann.name |