RFR: 8364583: ColorConvertOp fails for CMYK → RGB conversion
Harshitha Onkar
honkar at openjdk.org
Tue Nov 4 21:22:29 UTC 2025
On Mon, 3 Nov 2025 19:00:45 GMT, Sergey Bylokhov <serb at openjdk.org> wrote:
>> 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,...
@mrserb @prrace
Are we testing the else block - the one for **"possible non-ICC src, possible CSList, possible non-ICC dst"** with the test provided by Sergey?
Ln#872 in the else block has a similar line `color = srcCM.getNormalizedComponents(spixel, color, 0);` and the above test runs fine if normComponents is set to either color or null.
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/27785#discussion_r2492077834
More information about the client-libs-dev
mailing list