RFR: 8364583: ColorConvertOp fails for CMYK → RGB conversion
Sergey Bylokhov
serb at openjdk.org
Mon Nov 3 19:03:55 UTC 2025
On Fri, 24 Oct 2025 21:47:31 GMT, Phil Race <prr at openjdk.org> wrote:
>>> It can also be over-written at line 835.
>>
>> Interesting, is it possible that that line has the same bug?
>> `color = dstColorSpace.fromCIEXYZ(dstColor);`
>> Does dstColor always have the same number of components as CIEXYZ?
>>
>> Is the logic of using CIEXYZ for mix of non-/ICC source and non-/ICC destination actually correct?
>
> fromCIEXYZ is defined on ColorSpace, not ICC_ColorSpace.
>
> It requires 3 (or more) components, and then dstColorSpace will return an array of colors in its own colorspace.
> The dstColor parameter is always created with at least 3 components based on the dstNumComp
> And if there's no bug in dstColorSpace it should return an array of the right length for itself.
> So if there's a bug it isn't obvious to me.
Seems the destination handles it properly; I tested it with the following example:
import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.awt.image.ComponentColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.WritableRaster;
import static java.awt.color.ColorSpace.TYPE_2CLR;
import static java.awt.color.ColorSpace.TYPE_FCLR;
import static java.awt.color.ColorSpace.TYPE_GRAY;
public final class TestCCP {
private static final int WIDTH = 10;
private static final int HEIGHT = 10;
private static class CustomColorSpace extends ColorSpace {
private final int numComponents;
private CustomColorSpace(int type, int numComponents) {
super(type, numComponents);
this.numComponents = numComponents;
}
@Override
public float[] toRGB(float[] colorvalue) {
return new float[3];
}
@Override
public float[] fromRGB(float[] rgbvalue) {
return new float[numComponents];
}
@Override
public float[] toCIEXYZ(float[] colorvalue) {
return new float[3];
}
@Override
public float[] fromCIEXYZ(float[] colorvalue) {
return new float[numComponents];
}
}
private static final ColorSpace[] CS = {
ColorSpace.getInstance(ColorSpace.CS_CIEXYZ),
ColorSpace.getInstance(ColorSpace.CS_GRAY),
ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB),
ColorSpace.getInstance(ColorSpace.CS_PYCC),
ColorSpace.getInstance(ColorSpace.CS_sRGB),
new CustomColorSpace(TYPE_GRAY, 1),
new CustomColorSpace(TYPE_2CLR, 2),
new CustomColorSpace(TYPE_FCLR, 15)
};
public static void main(String[] args) {
for (ColorSpace srcCS : CS) {
for (ColorSpace fromCS : CS) {
for (ColorSpace toCS : CS) {
for (ColorSpace dstCS : CS) {
BufferedImage src = createTestImage(srcCS);
BufferedImage dst = createTestImage(dstCS);
new ColorConvertOp(fromCS, toCS, null).filter(src, dst);
}
}
}
}
}
private static BufferedImage createTestImage(ColorSpace cs) {
ComponentColorModel cm = new ComponentColorModel(cs, false, false,
Transparency.OPAQUE,
DataBuffer.TYPE_BYTE);
WritableRaster raster = cm.createCompatibleWritableRaster(WIDTH,
HEIGHT);
return new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
}
}
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/27785#discussion_r2487547644
More information about the client-libs-dev
mailing list