From dadd9cd1e8434cffaafc7406a864eaa55954cfb8 Mon Sep 17 00:00:00 2001 From: Renjith Kannath Pariyangad Date: Thu, 18 Jan 2024 01:23:30 +0000 Subject: [PATCH] 8316497: ColorConvertOp - typo for non-ICC conversions needs one-line fix Co-authored-by: Sergey Bylokhov Co-authored-by: Alexey Ivanov Reviewed-by: aivanov, serb --- .../java/awt/image/ColorConvertOp.java | 8 +- test/jdk/java/awt/color/NonICCFilterTest.java | 151 ++++++++++++++++++ 2 files changed, 155 insertions(+), 4 deletions(-) create mode 100644 test/jdk/java/awt/color/NonICCFilterTest.java diff --git a/src/java.desktop/share/classes/java/awt/image/ColorConvertOp.java b/src/java.desktop/share/classes/java/awt/image/ColorConvertOp.java index ced1e634dbb..1e7176e4b39 100644 --- a/src/java.desktop/share/classes/java/awt/image/ColorConvertOp.java +++ b/src/java.desktop/share/classes/java/awt/image/ColorConvertOp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -768,7 +768,7 @@ private BufferedImage nonICCBIFilter(BufferedImage src, } float[] srcMinVal = new float[iccSrcNumComp]; float[] srcInvDiffMinMax = new float[iccSrcNumComp]; - for (int i = 0; i < srcNumComp; i++) { + for (int i = 0; i < iccSrcNumComp; i++) { srcMinVal[i] = cs.getMinValue(i); srcInvDiffMinMax[i] = maxNum / (cs.getMaxValue(i) - srcMinVal[i]); } @@ -782,7 +782,7 @@ private BufferedImage nonICCBIFilter(BufferedImage src, } float[] dstMinVal = new float[iccDstNumComp]; float[] dstDiffMinMax = new float[iccDstNumComp]; - for (int i = 0; i < dstNumComp; i++) { + for (int i = 0; i < iccDstNumComp; i++) { dstMinVal[i] = cs.getMinValue(i); dstDiffMinMax[i] = (cs.getMaxValue(i) - dstMinVal[i]) / maxNum; } @@ -835,7 +835,7 @@ private BufferedImage nonICCBIFilter(BufferedImage src, dstDiffMinMax[i] + dstMinVal[i]; } if (nonICCDst) { - color = srcColorSpace.fromCIEXYZ(dstColor); + color = dstColorSpace.fromCIEXYZ(dstColor); for (int i = 0; i < dstNumComp; i++) { dstColor[i] = color[i]; } diff --git a/test/jdk/java/awt/color/NonICCFilterTest.java b/test/jdk/java/awt/color/NonICCFilterTest.java new file mode 100644 index 00000000000..bddd89ed6b3 --- /dev/null +++ b/test/jdk/java/awt/color/NonICCFilterTest.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.GradientPaint; +import java.awt.Graphics2D; +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; + +/* + * @test + * @bug 8316497 + * @summary Verifies Color filter on non-ICC profile + */ +public final class NonICCFilterTest { + private static final int WIDTH = 100; + private static final int HEIGHT = 100; + + private enum ColorSpaceSelector { + GRAY, + RGB, + PYCC, + WRAPPED_GRAY, + WRAPPED_RGB, + WRAPPED_PYCC + } + + private static final class TestColorSpace extends ColorSpace { + + private final ColorSpace cs; + + TestColorSpace(ColorSpace cs) { + super(cs.getType(), cs.getNumComponents()); + this.cs = cs; + } + + @Override + public float[] toRGB(float[] colorvalue) { + return cs.toRGB(colorvalue); + } + + @Override + public float[] fromRGB(float[] rgbvalue) { + return cs.fromRGB(rgbvalue); + } + + @Override + public float[] toCIEXYZ(float[] colorvalue) { + return cs.toCIEXYZ(colorvalue); + } + + @Override + public float[] fromCIEXYZ(float[] xyzvalue) { + return cs.fromCIEXYZ(xyzvalue); + } + } + + private static BufferedImage createTestImage(final ColorSpace cs) { + ComponentColorModel cm = new ComponentColorModel(cs, false, false, + Transparency.OPAQUE, DataBuffer.TYPE_BYTE); + WritableRaster raster = cm.createCompatibleWritableRaster(WIDTH, HEIGHT); + BufferedImage img = new BufferedImage(cm, raster, false, null); + + Graphics2D g = img.createGraphics(); + GradientPaint gp = new GradientPaint(0, 0, Color.GREEN, + raster.getWidth(), raster.getHeight(), Color.BLUE); + g.setPaint(gp); + g.fillRect(0, 0, raster.getWidth(), raster.getHeight()); + g.dispose(); + + return img; + } + + private static ColorSpace createCS(ColorSpaceSelector selector) { + return switch (selector) { + case GRAY -> ColorSpace.getInstance(ColorSpace.CS_GRAY); + case WRAPPED_GRAY -> new TestColorSpace(ColorSpace.getInstance(ColorSpace.CS_GRAY)); + + case RGB -> ColorSpace.getInstance(ColorSpace.CS_sRGB); + case WRAPPED_RGB -> new TestColorSpace(ColorSpace.getInstance(ColorSpace.CS_sRGB)); + + case PYCC -> ColorSpace.getInstance(ColorSpace.CS_PYCC); + case WRAPPED_PYCC -> new TestColorSpace(ColorSpace.getInstance(ColorSpace.CS_PYCC)); + }; + } + + private static boolean areImagesEqual(BufferedImage destTest, BufferedImage destGold) { + for (int x = 0; x < destTest.getWidth(); x++) { + for (int y = 0; y < destTest.getHeight(); y++) { + int rgb1 = destTest.getRGB(x, y); + int rgb2 = destGold.getRGB(x, y); + if (rgb1 != rgb2) { + System.err.println("x = " + x + ", y = " + y); + System.err.println("rgb1 = " + Integer.toHexString(rgb1)); + System.err.println("rgb2 = " + Integer.toHexString(rgb2)); + return false; + } + } + } + return true; + } + + public static void main(String[] args) { + BufferedImage srcTest = createTestImage(createCS(ColorSpaceSelector.WRAPPED_GRAY)); + BufferedImage destTest = createTestImage(createCS(ColorSpaceSelector.WRAPPED_RGB)); + + BufferedImage srcGold = createTestImage(createCS(ColorSpaceSelector.GRAY)); + BufferedImage destGold = createTestImage(createCS(ColorSpaceSelector.RGB)); + + ColorConvertOp gold = new ColorConvertOp(createCS(ColorSpaceSelector.PYCC), null); + gold.filter(srcTest, destTest); + gold.filter(srcGold, destGold); + + if (!areImagesEqual(destTest, destGold)) { + throw new RuntimeException("ICC test failed"); + } + + ColorConvertOp test = new ColorConvertOp(createCS(ColorSpaceSelector.WRAPPED_PYCC), null); + test.filter(srcTest, destTest); + test.filter(srcGold, destGold); + + if (!areImagesEqual(destTest, destGold)) { + throw new RuntimeException("Wrapper test failed"); + } + } +}