These are some notes on colour profiles issues with JP2.
Our test suite has a JP2 image with an embedded ColorSpin profile. This is a screenshot taken in Preview.app on macOS 10.12, which correctly identifies and renders the profile:
We have tests for both the Kakadu and OpenJPEG transformers that check if you have the config:
they can convert the image to a JPEG, and the colours are correct.
Previously this just checked that the images had different histograms, which is a fairly feeble test – making every pixel black would also pass! I’ve made the test a bit more specific, looking for the red stripe at the top – see #413.
This is the JPEG produced by Kakadu. It has no embedded colour profile, and the colours are correct. (Downsized for readability.)
This is the JPEG produced by OpenJPEG. It has no embedded colour profile, and the colours are mangled. (Downsized for readability.)
Curious!
Digging into the transformer code in transformers.py, the process for both these transformers goes something like this:
Make a shell call to kdu_expand or opj_decompress, which converts the JP2 into a BMP image
Attempt to convert the embedded colour profile to sRGB if required
Pass the new BMP into _derive_with_pil, which calls the Pillow transformer, and does any transformations defined by the user’s request – e.g. cropping, rotation
For Kakadu, here’s the image before and after step 2:
And likewise for the OpenJPEG transformer:
These were obtained by adding im.save(filename) inside transforms.py, then running the Loris test suite. We see that:
The JPEG produced by kdu_expand has mangled colours, and we need to fix them
The JPEG produced by opj_decompress has correct colours, and attempting to "fix" them actually makes matters worse
So I think our current Kakadu implementation is fine, but we need to think about changing the OpenJPEG implementation, possibly skipping the step where we fix the colour profile – it seems like OpenJPEG is already doing that for us?
I’d like to test this theory with more JP2 examples, and ideally not one where the colours cycle in quite such a neat way. I have at least one other test case (https://github.com/wellcometrust/platform/issues/734) – I’ll try it when I’m back at work on Monday.
These are some notes on colour profiles issues with JP2.
Our test suite has a JP2 image with an embedded ColorSpin profile. This is a screenshot taken in Preview.app on macOS 10.12, which correctly identifies and renders the profile:
We have tests for both the Kakadu and OpenJPEG transformers that check if you have the config:
they can convert the image to a JPEG, and the colours are correct.
Previously this just checked that the images had different histograms, which is a fairly feeble test – making every pixel black would also pass! I’ve made the test a bit more specific, looking for the red stripe at the top – see #413.
This is the JPEG produced by Kakadu. It has no embedded colour profile, and the colours are correct. (Downsized for readability.)
This is the JPEG produced by OpenJPEG. It has no embedded colour profile, and the colours are mangled. (Downsized for readability.)
Curious!
Digging into the transformer code in
transformers.py
, the process for both these transformers goes something like this:kdu_expand
oropj_decompress
, which converts the JP2 into a BMP image_derive_with_pil
, which calls the Pillow transformer, and does any transformations defined by the user’s request – e.g. cropping, rotationFor Kakadu, here’s the image before and after step 2:
And likewise for the OpenJPEG transformer:
These were obtained by adding
im.save(filename)
insidetransforms.py
, then running the Loris test suite. We see that:kdu_expand
has mangled colours, and we need to fix themopj_decompress
has correct colours, and attempting to "fix" them actually makes matters worseSo I think our current Kakadu implementation is fine, but we need to think about changing the OpenJPEG implementation, possibly skipping the step where we fix the colour profile – it seems like OpenJPEG is already doing that for us?
I’d like to test this theory with more JP2 examples, and ideally not one where the colours cycle in quite such a neat way. I have at least one other test case (https://github.com/wellcometrust/platform/issues/734) – I’ll try it when I’m back at work on Monday.