Thread: [Lcms-user] RGB to XYZ conversion
An ICC-based CMM for color management
Brought to you by:
mm2
From: Adrian Knagg-B. <aje...@gm...> - 2023-06-15 18:53:53
|
Hello, I'm trying to convert data from a source RGB colorspace to HSLuv (that color space is a bit niche but I specifically want to use it for a saturation stretching function). I did an initial test using the C implementation from hsluv.org and sRGB source data and it works well, but I want to be able to cope with any RGB source profile so my plan was to use LittleCMS to convert the source data to XYZ and then use the hsluv.org functions to convert XYZ to HSLuv. However I'm getting unexpected results from the initial conversion to XYZ and I wonder if I'm doing something wrong. Here's what I'm trying, first I make a transform: ``` cmsHPROFILE xyz = cmsCreateXYZProfile(); cmsUInt32Number formatrgb = TYPE_RGB_FLT_PLANAR; cmsUInt32Number formatxyz = TYPE_XYZ_FLT_PLANAR; cmsHTRANSFORM workingtoxyz = cmsCreateTransform(gfit.icc_profile, formatrgb, xyz, formatxyz, com.pref.icc.processing_intent, 0); cmsCloseProfile(xyz); ``` gfit.icc_profile is a cmsHPROFILE and contains a sRGB profile, and com.pref.processing_intent is set to INTENT_PERCEPTUAL: those work fine throughout the rest of the code. But when I apply it with cmsDoTransform() the effect on an image looks completely wrong compared with my initial test using hsluv's rgb2xyz() function. I tested the RGB to XYZ conversion using the following: ``` float test_rgb[] = {0.75f, 0.5f, 0.3f}; float test_xyz[]; printf("RGB test: %f %f %f\n", test_rgb[0], test_rgb[1], test_rgb[2]); hsluv_rgbtoxyz(test_rgb[0], test_rgb[1], test_rgb[2], &test_xyz[0], &test_xyz[1], &test_xyz[2]); printf("HSLuv rgb2xyz: %f %f %f\n", test_xyz[0], test_xyz[1], test_xyz[2]); cmsDoTransform(workingtoxyz, (void*) &test_rgb, (void*) &test_xyz, 1); printf("LCMS rgb2xyz: %f %f %f\n", test_xyz[0], test_xyz[1], test_xyz[2]); ``` And the results are completely different: HSLuv rgb2xyz: 0.305239 0.269471 0.105229 LCMS rgb2xyz: 0.160394 0.137083 0.040251 I assume I'm doing something wrong but I can't see what - grateful for any help you can offer. Thanks, Adrian. |
From: <mar...@li...> - 2023-06-15 20:06:43
|
Hello, I have written a small program to check this and found it works fine to me. At first glance I see a couple of things on your code, but didn't analyze in detail. float_xyz[] do not compile, you need to set the size, which at least should be 3. Another thing is the formatters TYPE_RGB_FLT_PLANAR and TYPE_XYZ_FLT_PLANAR that are not in lcms2.h, therefore you have defined them elsewhere. Check if correct. Anyway, this is the program I did that gives the right values. #include "lcms2.h" #define TYPE_RGB_FLT_PLANAR (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(4)|PLANAR_SH(1)) #define TYPE_XYZ_FLT_PLANAR (FLOAT_SH(1)|COLORSPACE_SH(PT_XYZ)|CHANNELS_SH(3)|BYTES_SH(4)|PLANAR_SH(1)) int main() { float rgb[] = { 0.75f, 0.5f, 0.3f }; float xyz[3]; cmsHPROFILE srgb_icc = cmsCreate_sRGBProfile(); cmsHPROFILE xyz_icc = cmsCreateXYZProfile(); cmsHTRANSFORM workingtoxyz = cmsCreateTransform(srgb_icc, TYPE_RGB_FLT_PLANAR, xyz_icc, TYPE_XYZ_FLT_PLANAR, INTENT_PERCEPTUAL, 0); cmsCloseProfile(xyz_icc); cmsCloseProfile(srgb_icc); cmsDoTransform(workingtoxyz, rgb, xyz, 1); printf("LCMS rgb2xyz: %f %f %f\n", xyz[0], xyz[1], xyz[2]); cmsDeleteTransform(workingtoxyz); return 0; } Output: LCMS rgb2xyz: 0.320747 0.274139 0.080336 You can verify the values using this calculator http://www.brucelindbloom.com/index.html?ColorCalculator.html Hope that helps Marti Maria The LittleCMS Project https://www.littlecms.com > -----Original Message----- > From: Adrian Knagg-Baugh <aje...@gm...> > Sent: Thursday, June 15, 2023 8:54 PM > To: lcm...@li... > Subject: [Lcms-user] RGB to XYZ conversion > > Hello, > > I'm trying to convert data from a source RGB colorspace to HSLuv (that color > space is a bit niche but I specifically want to use it for a saturation stretching > function). I did an initial test using the C implementation from hsluv.org and > sRGB source data and it works well, but I want to be able to cope with any RGB > source profile so my plan was to use LittleCMS to convert the source data to > XYZ and then use the hsluv.org functions to convert XYZ to HSLuv. > > However I'm getting unexpected results from the initial conversion to XYZ and > I wonder if I'm doing something wrong. Here's what I'm trying, first I make a > transform: > ``` > cmsHPROFILE xyz = cmsCreateXYZProfile(); > cmsUInt32Number formatrgb = TYPE_RGB_FLT_PLANAR; > cmsUInt32Number formatxyz = TYPE_XYZ_FLT_PLANAR; > cmsHTRANSFORM workingtoxyz = cmsCreateTransform(gfit.icc_profile, > formatrgb, xyz, formatxyz, com.pref.icc.processing_intent, 0); > cmsCloseProfile(xyz); > ``` > gfit.icc_profile is a cmsHPROFILE and contains a sRGB profile, and > com.pref.processing_intent is set to INTENT_PERCEPTUAL: those work fine > throughout the rest of the code. > But when I apply it with cmsDoTransform() the effect on an image looks > completely wrong compared with my initial test using hsluv's rgb2xyz() > function. I tested the RGB to XYZ conversion using the following: > ``` > float test_rgb[] = {0.75f, 0.5f, 0.3f}; > float test_xyz[]; > printf("RGB test: %f %f %f\n", test_rgb[0], test_rgb[1], test_rgb[2]); > hsluv_rgbtoxyz(test_rgb[0], test_rgb[1], test_rgb[2], &test_xyz[0], > &test_xyz[1], &test_xyz[2]); > printf("HSLuv rgb2xyz: %f %f %f\n", test_xyz[0], test_xyz[1], test_xyz[2]); > cmsDoTransform(workingtoxyz, (void*) &test_rgb, (void*) &test_xyz, 1); > printf("LCMS rgb2xyz: %f %f %f\n", test_xyz[0], test_xyz[1], test_xyz[2]); ``` > And the results are completely different: > > HSLuv rgb2xyz: 0.305239 0.269471 0.105229 LCMS rgb2xyz: 0.160394 > 0.137083 0.040251 > > I assume I'm doing something wrong but I can't see what - grateful for any > help you can offer. > > Thanks, > > Adrian. > > > _______________________________________________ > Lcms-user mailing list > Lcm...@li... > https://lists.sourceforge.net/lists/listinfo/lcms-user |