我正在尝试使用lcms2 lib通过icc配置文件将CMYK转换为RGB。 我在http://www.littlecms.com/1/TUTORIAL.TXT上找到了一些示例代码 - >示例1:如何将RGB转换为CMYK并返回 但是,如果我在我的代码中使用两个给定的配置文件,我收到的结果值接近0。 我的代码是:
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);
我得到的输出是(来自qDebug行):
...
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
...
我做错了什么?应该找到icc配置文件。如果我错误的路径 进入功能,应用程序崩溃了,那么问题出在哪里呢? 非常感谢你。
此致 马克西姆
答案 0 :(得分:2)
这里有一些问题:
TYPE_CMYK_8
和TYPE_RGB_8
),但是您将双打传递给cmsDoTransform()
- cmy
和{ {1}}是双数组。您应该将8位数组传递给rgb
。cmsDoTransform()
(3)值传递给CMY
,但您应该为每个像素传递cmsDoTransform()
(4)个值。 CMYK每个像素有四个组件,因此您需要将每个像素的4个值传递给CMYK
。cmsDoTransform()
效率不高。 LCMS经过优化,可以处理像素阵列,将整个图像或至少每条扫描线传递到cmsDoTransform()
会更高效。我不确定为什么要按cmsDoTransform()
递增in
指针。这意味着输入缓冲区用于cinfo.output_width * 4
(下一行向下),而输出缓冲区用于outImage->scanLine(j+1)
。这有什么理由吗?我在下面的代码中省略了它。
outImage->scanLine(j)
我假设您在使用qRgb和qDebug时正在与QImages合作。 QImages通常是每像素32位图像 - ARGB或XRGB(忽略alpha分量)。如果是这种情况,那么在创建转换时,您将需要使用// Why add "cinfo.output_width * 4” here?
uchar *in = outImage->scanLine(j) + cinfo.output_width * 4;
或TYPE_RGBA_8
,具体取决于为QImage存储Alpha通道的位置 - LCMS将忽略Alpha通道。
通过所有这些修改,代码看起来像这样(未经测试):
TYPE_ARGB_8
您可以通过直接在QImage的数据缓冲区上操作,在一次调用中完成所有操作:
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);
}