Reputation: 11
I'm trying to use lcms2 lib to convert CMYK to RGB through icc profiles. I have found some example code on http://www.littlecms.com/1/TUTORIAL.TXT -> Sample 1: How to convert RGB to CMYK and back But if I use that in my code with two given profiles I receive near 0 resulting values. My code is:
cmsHPROFILE hInProfile, hOutProfile;
cmsHTRANSFORM hTransform;
int i;
hInProfile = cmsOpenProfileFromFile("/Users/me/Downloads/ECI_Offset_2009/ISOcoated_v2_300_eci.icc", "r");
hOutProfile = cmsOpenProfileFromFile("/Users/me/Downloads/profiles/sRGB Color Space Profile.ICM", "r");
hTransform = cmsCreateTransform(hInProfile,
TYPE_CMYK_8,
hOutProfile,
TYPE_RGB_8,
INTENT_PERCEPTUAL, 0);
for (uint j = 0; j < cinfo.output_height; ++j) {
uchar *in = outImage->scanLine(j) + cinfo.output_width * 4;
QRgb *out = (QRgb*)outImage->scanLine(j);
for (uint i = cinfo.output_width; i--; ) {
double k = in[3]/255.0;
double cmy[3] = {in[0]/255.0 , in[1]/255.0 , in[2]/255.0 };//scale to 0.0...1.0
double rgb[3];
cmsDoTransform(hTransform, cmy, &rgb, 1);
qDebug() << cmy[0] << cmy[1] << cmy[2] << "|" << rgb[0] << rgb[1] << rgb[2];
out[i] = qRgb(rgb[0]*255, rgb[1]*255, rgb[2]*255);
}
}
cmsDeleteTransform(hTransform);
cmsCloseProfile(hInProfile);
cmsCloseProfile(hOutProfile);
The output I get is (from the qDebug line):
...
0.356863 0.196078 0.345098 | 2.1432e-299 1.35934e-312 -1.81433e-196
0.490196 0.294118 0.482353 | 2.1432e-299 1.35934e-312 -1.81433e-196
0.537255 0.258824 0.466667 | 2.1432e-299 1.35934e-312 -1.81433e-196
0.419608 0.227451 0.364706 | 2.1432e-299 1.35934e-312 -1.81433e-196
0.34902 0.305882 0.345098 | 2.1432e-299 1.35934e-312 -1.81433e-196
0.14902 0.133333 0.0980392 | 2.1432e-299 1.35934e-312 -1.81433e-196
...
What I'm doing wrong? The icc profile files should be found. If I put wrong paths into the functions, the application crashed, so where is the problem then? Thank you very much.
Regards, Maxim
Upvotes: 0
Views: 1720
Reputation: 1777
There’s a few issues here:
TYPE_CMYK_8
and TYPE_RGB_8
) when you create the transform, but you’re passing doubles to cmsDoTransform()
- cmy
and rgb
are double arrays. You should be passing 8-bit arrays to cmsDoTransform()
.CMY
(3) values to cmsDoTransform()
but you should be passing CMYK
(4) values for each pixel. CMYK has four components per pixel so you need to pass 4 values for each pixel to cmsDoTransform()
.cmsDoTransform()
for each pixels isn’t very efficient. LCMS is optimized to work on arrays of pixels, it would be much more efficient to pass the entire image, or at least each scan line to cmsDoTransform()
.I’m not sure why you’re incrementing the in
pointer by cinfo.output_width * 4
. This means that the input buffer is for outImage->scanLine(j+1)
(the next line down) while the output buffer is for outImage->scanLine(j)
. Is there a reason for that? I’ve omitted it in my code below.
// Why add "cinfo.output_width * 4” here?
uchar *in = outImage->scanLine(j) + cinfo.output_width * 4;
I’m assuming you’re working with QImages given the use of qRgb and qDebug. QImages are usually 32-bits per pixel images - either ARGB or XRGB (ignored alpha component). If that’s the case then you’ll want to use either TYPE_RGBA_8
or TYPE_ARGB_8
when creating the transform depending on where the Alpha channel is stored for the QImage - LCMS will ignore the alpha channel.
With all of those modifications the code would look something like this (untested):
hTransform = cmsCreateTransform(hInProfile,
TYPE_CMYK_8,
hOutProfile,
TYPE_ARGB_8, // ARGB is most likely for QImage
INTENT_PERCEPTUAL, 0);
for (uint j = 0; j < cinfo.output_height; ++j) {
uchar *in = outImage->scanLine(j);
uchar *out = outImage->scanLine(j);
cmsDoTransform(hTransform, in, out, cinfo.output_width);
}
You can probably do it all in a single call by operating directly on the QImage’s data buffer:
hTransform = cmsCreateTransform(hInProfile,
TYPE_CMYK_8,
hOutProfile,
TYPE_ARGB_8, // ARGB is most likely for QImage
INTENT_PERCEPTUAL, 0);
uchar *in = outImage->bits(); // bits() is equivalent to scanLine(0)
uchar *out = outImage->bits();
cmsDoTransform(hTransform, in, out, outImage->byteCount() / sizeof(QRgb));
Upvotes: 2