[Lcms-user] RGB-to-XYZ-to-RGB weirdness
An ICC-based CMM for color management
Brought to you by:
mm2
From: Derek B. N. <de...@gl...> - 2017-10-20 20:08:25
|
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 |