Opened 4 years ago

Closed 3 years ago

#5097 closed defect (fixed)

JPEG CMYK values inverted

Reported by: cleo Owned by: warmerdam
Priority: normal Milestone:
Component: GDAL_Raster Version: 1.9.2
Severity: normal Keywords:


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).

Some background:

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:

  1. Does turning off RGB conversion always return the original data in the file?
  1. 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).
  1. 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.

Attachments (2)

jpgdataset.cpp.1.9.1.patch (2.8 KB) - added by cleo 4 years ago.
jpgdataset.cpp.1.10.patch (2.8 KB) - added by cleo 4 years ago.

Download all attachments as: .zip

Change History (15)

comment:1 Changed 4 years ago by warmerdam

Status: newassigned


Is your problem with the JPEG driver or the GeoTIFF driver or both?

If libjpeg represents CYMK in inverse format, it does seem like we will need to adjust it on the fly in the read and write methods which is slightly annoying but not terribly expensive.

Would you be interested in preparing a proposed patch?

Some notice of this fix will be needed for the community since it is somewhat disruptive. Possibly we will pursue it only in trunk, not 1.10 branch.

comment:2 Changed 4 years ago by cleo

The tiff driver seems to be fine (for RGB and CMYK, though I haven't tested any other colour spaces yet).

The bug I listed at the end of the main ticket text happens in the JPEG driver (YCCK bug). This is simply moving a line to its appropriate location. This should be fixed on the earliest branch possible as it's simply incorrect right now.

As for the CMYK inverse format, I would be happy to provide a patch for this. I'll try and provide it within the next couple days as I have some more work to complete before I can get to this. I'll include the YCCK bug fix as well.

comment:3 Changed 4 years ago by cleo

I should add that my only concern with the tiff driver was that each driver has its own way of telling it to load raw bands. Not sure how to start a discussion on this or if it's too unmanageable a task to have some consistency across drivers for similar attributes (raw bands & DPI for example).

Changed 4 years ago by cleo

Attachment: jpgdataset.cpp.1.9.1.patch added

Changed 4 years ago by cleo

Attachment: jpgdataset.cpp.1.10.patch added

comment:4 Changed 4 years ago by cleo

I provide two patches. I'm currently working off of 1.9.1, but I provided a patch for 1.10 as well. There is one line different between the two.

comment:5 Changed 4 years ago by warmerdam

I've tried digging around the web for CMYK images without apparent success.

For instance if I download:

and then do:

 gdalinfo --config GDAL_JPEG_TO_RGB YES Channel_digital_image_CMYK_color.jpg 

I get:

Image Structure Metadata:
Band 1 Block=500x1 Type=Byte, ColorInterp=Red
  Overviews: 250x167
  Image Structure Metadata:
Band 2 Block=500x1 Type=Byte, ColorInterp=Green
  Overviews: 250x167
  Image Structure Metadata:
Band 3 Block=500x1 Type=Byte, ColorInterp=Blue
  Overviews: 250x167
  Image Structure Metadata:

I had expected to see the SOURCE_COLOR_SPACE as CMYK. This without the patch applied in GDAL trunk.

comment:6 Changed 4 years ago by cleo

That image is mislabeled. It is CYYK. However, when you open the image with GDAL, it will report CMYK for the colour interpretation of the bands if you open it with raw bands. The SOURCE_COLOR_SPACE will be correct though.

If you want a cmyk image, I believe there is one in gdal's test images called rgb_ntf_cmyk.jpg. This one should show up green, but shows up blue if loaded as raw cmyk bands.

comment:7 Changed 4 years ago by cleo

Let me know if you want me to generate a CMYK image and I will attach it.

comment:8 Changed 4 years ago by cleo

Any chance of getting this patch applied?

comment:9 Changed 4 years ago by cleo

Could this patch be applied please? At least the part where the colour space is misreported by GetColourInterpretation?() when in raw mode.

comment:10 Changed 4 years ago by Even Rouault

I've applied the most "obvious" part of your patch in r26479 "JPEG: return YCbCrK raw data for YCbCrK JPEG in GDAL_JPEG_TO_RGB = NO mode (instead of CMYK as before) (patch from cleo, #5097)"

As far as inverted CMYK vs normal CMYK, it might be a complicated topic. I've found another discussion in . I'm not sure to have fully understood it, but it appears that both kind of files could be found.

comment:11 Changed 4 years ago by cleo

Thanks you! I appreciate it. The correct color interpretation was my main concern.

As for inverted CMYK, it seems it's an Adobe specific issue. Since it's not consistent, then I do not want any changes here. I suggest closing this.

Thanks again!

comment:12 Changed 3 years ago by Jukka Rahkonen

The creator of the ticket suggested closing. I suggest the same.

comment:13 Changed 3 years ago by Even Rouault

Resolution: fixed
Status: assignedclosed
Note: See TracTickets for help on using tickets.