I've been using the MagickWand API (ImageMagick 6.4.2) to extract pixel data from various image types, and do some colorspace conversion. The colorspaces of interest are RGB (RGBColorspace), CIELAB (LabColorspace), CMYK (CMYKColorspace), Grayscale (GrayscaleColorspace), and Kodak PhotoYCC (YCCColorspace, not to be confused with YCbCr or YPbPr).
I came across an interesting anomaly: the colorspace conversions defined in colorspace.c work great, except when involving YCC. The equations listed seem fine (the comments below about scaling and such are ambiguous, but that's a separate issue. Said equations are excerpted below:
Code: Select all
/*
Initialize YCC tables:
Y = 0.29900*R+0.58700*G+0.11400*B
C1= -0.29900*R-0.58700*G+0.88600*B
C2= 0.70100*R-0.58700*G-0.11400*B
YCC is scaled by 1.3584. C1 zero is 156 and C2 is at 137.
*/
Code: Select all
/*
Initialize YCC tables:
R = Y +1.340762*C2
G = Y-0.317038*C1-0.682243*C2
B = Y+1.632639*C1
YCC is scaled by 1.3584. C1 zero is 156 and C2 is at 137.
*/
Perhaps I'm misunderstanding something, but it seems wrong that if I have a pixel value (quantum_depth = 32) of {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF} in RGB, convert it to YCC via RGBTransformImage, then back to RGB via [TransformImageRGB[/i], that the resulting pixel value is {0x00000000,0x00000000,0x0000000}.
I've found the following two mathematically-equivalent fixes:
In my code
Code: Select all
//After the YCC->RGB MagickSetImageColorspace() call, but BEFORE we write out to file
//Scale by 81000 if we're doing YCC to RGB.
//No root cause found yet, but without this, if you convert RGB->YCC->RGB, the first conversion goes fine, but the second yields
//a black image (all values are non-zero, but way less than 1 LSB).
if(inputColorspace == YCCColorspace)
{
status=MagickEvaluateImage(magick_wand, MultiplyEvaluateOperator, 81000.0f);
if(status == MagickFalse)
ThrowWandException(magick_wand);
}
Code: Select all
case YCCColorspace:
{
pixel.red/=1.3584000f;
pixel.red*=81000.0f; //FIX
pixel.green/=1.3584000f;
pixel.green*=81000.0f; //FIX
pixel.blue/=1.3584000f;
pixel.blue*=81000.0f; //FIX
break;
}
Anyway, thanks in advance for looking at this!
-Matt