JPEG CMYK values inverted
|Reported by:||cleo||Owned by:||warmerdam|
When loading a CMYK JPEG image with GDAL_JPEG_TO_RGB set to NO, I do get the CMYK bands, but JPEG stores them inverted (255 - Cyan, for example).
I could not find the design docs for the automatic conversion or what the other colour spaces are supposed to return. I understand that if it is truly meant to return the raw bands (original data), then this is working exactly as it should. OTOH, this is not CMYK, but inverted CMYK. So it becomes impossible to use generic code, or use this with colour ICC profiles, etc. w/o doing more conversions beforehand and this means having driver specific code which contradicts the purpose of having a generic library.
Normally, CMYK is converted to RGB with (normalized values):
R = (1 - ((C * (1-K)) + K))
R = (1 - ((C - CK) + K))
R = (1 - C + CK - K)
R = 1 - C - K + CK
If you start out with inverted values:
R = IC * IK
R = (1 - C) * (1 - K)
R = 1 - C - K + CK
And you get the same result with just one multiply (and a division by 255).
My questions are as follows:
- Does turning off RGB conversion always return the original data in the file?
- If #1 is yes, then would it make sense to (also) have a way to return values that are appropriate for the colour space. IOW, CMYK values should not be inverted where we can use these values to convert to RGB by using the embedded colour profile (or the standard conversion equations).
- TIFF's use "GTIFF_RAW:" file prefix to load the original data while JPEG uses GDAL_JPEG_TO_RGB=NO. I haven't looked at other formats. Should there not be a more consistent way of doing this across all drivers? I made the same comment about DPI in another ticket. Perhaps other attributes should be more consistent across drivers as well.
I think this part is definitely a bug...
I noticed that I could not get the CMYK bands from this YCCK JPEG image:
The comment in the code says libjpeg automatically converts to CMYK since it sets poDS->sDInfo.out_color_space = JCS_CMYK. But it doesn't change the poDS->eGDALColorSpace to CMYK. This means that it's returning CMYK bands with colour interpretation of YCbCrK.
If I assume that returning non-rgb converted bands should return the original data, then the fix would be to move "poDS->sDInfo.out_color_space = JCS_CMYK" into the first block of the if statement above it in jpgdataset.cpp where the gdal colour space is set to JCS_RGB. This would leave the GDAL colour space intact and correct unless there is automatic conversion to RGB.
I have confirmed that the bands currently being returned as YCbCrK are indeed inverted CMYK bands and are not the YCCK bands as expected.