Re: [Lcms-user] RGB-to-XYZ-to-RGB weirdness
An ICC-based CMM for color management
Brought to you by:
mm2
From: Martí M. <mar...@li...> - 2017-10-23 11:20:14
|
Hi, XYZ gamut is huge, so using tetrahedral interpolation from XYZ to RGB is likely to result in errors. I would use cmsFLAGS_NOOPTIMIZE in xyzToRGB color transform to force all the math. Another option is to use float or double values. Regards Marti On 10/20/2017 9:50 PM, Derek B. Noonburg wrote: > I'm working on some color management code, using LCMS2, and I'm running > into some behavior that I don't understand. > > If I convert sRGB to XYZ and then back to sRGB, I get significantly > different RGB values at the output. > > If I do sRGB -> Lab -> sRGB, I get exactly the same values back. > > The really weird part is: if I convert XYZ to Lab and then to sRGB (sRGB > -> XYZ -> Lab -> sRGB), I get the expected RGB values again. So the > sRGB-to-XYZ conversion is fine, but the XYZ-to-sRGB conversion is wrong. > Or, more likely, I'm doing something wrong... but I'm not sure what. > > Can someone explain what's going on here? > > I'm running LCMS 2.8 on Linux. Here's my test program: > > #include <stdio.h> > #include <lcms2.h> > > int main(int argc, char *argv[]) { > cmsHPROFILE rgbProfile = cmsCreate_sRGBProfile(); > cmsHPROFILE labProfile = cmsCreateLab2Profile(NULL); > cmsHPROFILE xyzProfile = cmsCreateXYZProfile(); > cmsHTRANSFORM rgbToLab = cmsCreateTransform(rgbProfile, TYPE_RGB_8, > labProfile, TYPE_Lab_16, > INTENT_ABSOLUTE_COLORIMETRIC, > 0); > cmsHTRANSFORM labToRGB = cmsCreateTransform(labProfile, TYPE_Lab_16, > rgbProfile, TYPE_RGB_8, > INTENT_ABSOLUTE_COLORIMETRIC, > 0); > cmsHTRANSFORM rgbToXYZ = cmsCreateTransform(rgbProfile, TYPE_RGB_8, > xyzProfile, TYPE_XYZ_16, > INTENT_ABSOLUTE_COLORIMETRIC, > 0); > cmsHTRANSFORM xyzToRGB = cmsCreateTransform(xyzProfile, TYPE_XYZ_16, > rgbProfile, TYPE_RGB_8, > INTENT_ABSOLUTE_COLORIMETRIC, > 0); > > unsigned char rgbIn[3] = {0x6a, 0x3c, 0x31}; > > // rgb1 matches rgbIn > unsigned short lab1[3]; > unsigned char rgb1[3]; > cmsDoTransform(rgbToLab, rgbIn, lab1, 1); > cmsDoTransform(labToRGB, lab1, rgb1, 1); > printf("RGB %02x %02x %02x -> Lab %04x %04x %04x -> RGB %02x %02x %02x\n", > rgbIn[0], rgbIn[1], rgbIn[2], > lab1[0], lab1[1], lab1[2], > rgb1[0], rgb1[1], rgb1[2]); > > // rgb2 does not match rgbIn > unsigned short xyz2[3]; > unsigned char rgb2[3]; > cmsDoTransform(rgbToXYZ, rgbIn, xyz2, 1); > cmsDoTransform(xyzToRGB, xyz2, rgb2, 1); > printf("RGB %02x %02x %02x -> Lab %04x %04x %04x -> RGB %02x %02x %02x\n", > rgbIn[0], rgbIn[1], rgbIn[2], > xyz2[0], xyz2[1], xyz2[2], > rgb2[0], rgb2[1], rgb2[2]); > > // rgb3 matches rgbIn > cmsCIEXYZ xyzF; > cmsCIELab labF; > unsigned short lab3[3]; > unsigned char rgb3[3]; > cmsXYZEncoded2Float(&xyzF, xyz2); > cmsXYZ2Lab(NULL, &labF, &xyzF); > cmsFloat2LabEncoded(lab3, &labF); > cmsDoTransform(labToRGB, lab3, rgb3, 1); > printf("RGB %02x %02x %02x -> XYZ %04x %04x %04x -> Lab %04x %04x %04x -> RGB %02x %02x %02x\n", > rgbIn[0], rgbIn[1], rgbIn[2], > xyz2[0], xyz2[1], xyz2[2], > lab3[0], lab3[1], lab3[2], > rgb3[0], rgb3[1], rgb3[2]); > } > > - Derek > > > ------------------------------------------------------------------------------ > Check out the vibrant tech community on one of the world's most > engaging tech sites, Slashdot.org! http://sdm.link/slashdot > _______________________________________________ > Lcms-user mailing list > Lcm...@li... > https://lists.sourceforge.net/lists/listinfo/lcms-user > |