I have a BufferedImage with an invalid color profile. I want to replace the color profile with an ICC_Profile without recomputing the pixel values in the image. How can I do that?
In particular the com.sun.imageio.plugins.png.PNGImageReader reads an image with a DCI-P3 ICC profile and produces a BufferedImage with a CS_sRGB ColorSpace but the pixel values correspond to the original DCI-P3 color space and the resulting image has the wrong colors.
If I could just swap the sRGB ColorSpace with a DCI-P3 ColorSpace from the ICC profile the colors would be correct. If I run a ColorConvertOp with a destination ICC_Profile on the image then the resulting colors are (differently) wrong because it interprets the source pixels using the wrong sRGB ColorSpace.
I haven't actually tried this, as there's no code in the question to verify against, but I believe this should work:
If you have the DCI-P3 profile available, you could just create a Java
ColorSpacefrom that, then create aColorModelusing this color space. The new color model needs to have the same type and the same number of components as that in the original image. Finally, create a newBufferedImageusing this color model and theRasterof the original image. Something like this:The above is assuming that your image is RGB (no alpha/transparency), 8 bits/sample and that the original image has a
ComponentColorModel. If this is incorrect, you need to modify the color model accordingly. Some common examples:ComponentColorModelwith alpha, 16 bits/sample:DirectColorModelwith alpha, 8 bits/sample, ARGB order:As there is no duplication or conversion of the pixel data in this case, this operation should be really fast. But it will produce a
TYPE_CUSTOMBufferedImagedue to the non-standard ICC profile. It will look correct, but might be slow to paint on screen. If you need an image that is fast to paint, usingColorConvertOpmight be a better option.It should be possible to do an in-place conversion on the raster, directly from the DCI-P3 profile to sRGB like this: