diff --git a/src/java.desktop/share/classes/sun/java2d/cmm/lcms/LCMSImageLayout.java b/src/java.desktop/share/classes/sun/java2d/cmm/lcms/LCMSImageLayout.java index 8101c568d0b..d2da59617f1 100644 --- a/src/java.desktop/share/classes/sun/java2d/cmm/lcms/LCMSImageLayout.java +++ b/src/java.desktop/share/classes/sun/java2d/cmm/lcms/LCMSImageLayout.java @@ -52,16 +52,22 @@ final class LCMSImageLayout { static int CHANNELS_SH(int x) { return x << 3; } + + static int PREMUL_SH(int x) { + return x << 23; + } private static final int SWAPFIRST = 1 << 14; private static final int DOSWAP = 1 << 10; - private static final int PT_GRAY_8 = CHANNELS_SH(1) | BYTES_SH(1); - private static final int PT_GRAY_16 = CHANNELS_SH(1) | BYTES_SH(2); - private static final int PT_RGB_8 = CHANNELS_SH(3) | BYTES_SH(1); - private static final int PT_RGBA_8 = PT_RGB_8 | EXTRA_SH(1); - private static final int PT_ARGB_8 = PT_RGBA_8 | SWAPFIRST; - private static final int PT_BGR_8 = PT_RGB_8 | DOSWAP; - private static final int PT_ABGR_8 = PT_BGR_8 | EXTRA_SH(1); -// private static final int PT_BGRA_8 = PT_ABGR_8 | SWAPFIRST; + private static final int PT_GRAY_8 = CHANNELS_SH(1) | BYTES_SH(1); + private static final int PT_GRAY_16 = CHANNELS_SH(1) | BYTES_SH(2); + private static final int PT_RGB_8 = CHANNELS_SH(3) | BYTES_SH(1); + private static final int PT_RGBA_8 = PT_RGB_8 | EXTRA_SH(1); + private static final int PT_ARGB_8 = PT_RGBA_8 | SWAPFIRST; + private static final int PT_ARGB_8_PREMUL = PT_ARGB_8 | PREMUL_SH(1); + private static final int PT_BGR_8 = PT_RGB_8 | DOSWAP; + private static final int PT_ABGR_8 = PT_BGR_8 | EXTRA_SH(1); + private static final int PT_ABGR_8_PREMUL = PT_ABGR_8 | PREMUL_SH(1); +// private static final int PT_BGRA_8 = PT_ABGR_8 | SWAPFIRST; private static final int SWAP_ENDIAN = ByteOrder.nativeOrder() == LITTLE_ENDIAN ? DOSWAP : 0; private static final int DT_BYTE = 0; @@ -148,6 +154,9 @@ final class LCMSImageLayout { case BufferedImage.TYPE_INT_RGB: l.pixelType = PT_ARGB_8 ^ SWAP_ENDIAN; break; + case BufferedImage.TYPE_INT_ARGB_PRE: + l.pixelType = PT_ARGB_8_PREMUL ^ SWAP_ENDIAN; + break; case BufferedImage.TYPE_INT_ARGB: l.pixelType = PT_ARGB_8 ^ SWAP_ENDIAN; break; @@ -160,6 +169,9 @@ final class LCMSImageLayout { case BufferedImage.TYPE_4BYTE_ABGR: l.pixelType = PT_ABGR_8; break; + case BufferedImage.TYPE_4BYTE_ABGR_PRE: + l.pixelType = PT_ABGR_8_PREMUL; + break; case BufferedImage.TYPE_BYTE_GRAY: l.pixelType = PT_GRAY_8; break; @@ -172,10 +184,7 @@ final class LCMSImageLayout { * has to be supported. */ ColorModel cm = image.getColorModel(); - // lcms as of now does not support pre-alpha - if (!cm.isAlphaPremultiplied() - && cm instanceof ComponentColorModel ccm) - { + if (cm instanceof ComponentColorModel ccm) { // verify whether the component size is fine int[] cs = ccm.getComponentSize(); for (int s : cs) { @@ -183,7 +192,7 @@ final class LCMSImageLayout { return null; } } - return createImageLayout(image.getRaster(), cm.hasAlpha()); + return createImageLayout(image.getRaster(), cm); } return null; } @@ -194,6 +203,7 @@ final class LCMSImageLayout { switch (image.getType()) { case BufferedImage.TYPE_INT_RGB: case BufferedImage.TYPE_INT_ARGB: + case BufferedImage.TYPE_INT_ARGB_PRE: case BufferedImage.TYPE_INT_BGR: do { IntegerComponentRaster intRaster = (IntegerComponentRaster) @@ -209,13 +219,14 @@ final class LCMSImageLayout { case BufferedImage.TYPE_3BYTE_BGR: case BufferedImage.TYPE_4BYTE_ABGR: + case BufferedImage.TYPE_4BYTE_ABGR_PRE: do { ByteComponentRaster byteRaster = (ByteComponentRaster) image.getRaster(); l.nextRowOffset = byteRaster.getScanlineStride(); l.nextPixelOffset = byteRaster.getPixelStride(); - int firstBand = image.getSampleModel().getNumBands() - 1; + int firstBand = byteRaster.getSampleModel().getNumBands() - 1; l.offset = byteRaster.getDataOffset(firstBand); l.dataArray = byteRaster.getDataStorage(); l.dataArrayLength = byteRaster.getDataStorage().length; @@ -320,7 +331,7 @@ final class LCMSImageLayout { return checkIndex(res, Integer.MAX_VALUE); } - static LCMSImageLayout createImageLayout(Raster r, boolean hasAlpha) { + static LCMSImageLayout createImageLayout(Raster r, ColorModel cm) { LCMSImageLayout l = new LCMSImageLayout(); if (r instanceof ByteComponentRaster && r.getSampleModel() instanceof ComponentSampleModel) { @@ -329,8 +340,12 @@ final class LCMSImageLayout { ComponentSampleModel csm = (ComponentSampleModel)r.getSampleModel(); int numBands = br.getNumBands(); + boolean hasAlpha = cm != null && cm.hasAlpha(); l.pixelType = (hasAlpha ? CHANNELS_SH(numBands - 1) | EXTRA_SH(1) : CHANNELS_SH(numBands)) | BYTES_SH(1); + if (hasAlpha && cm.isAlphaPremultiplied()) { + l.pixelType |= PREMUL_SH(1); + } int[] bandOffsets = csm.getBandOffsets(); BandOrder order = BandOrder.getBandOrder(bandOffsets); diff --git a/src/java.desktop/share/classes/sun/java2d/cmm/lcms/LCMSTransform.java b/src/java.desktop/share/classes/sun/java2d/cmm/lcms/LCMSTransform.java index 0d26022617d..077b940d4ca 100644 --- a/src/java.desktop/share/classes/sun/java2d/cmm/lcms/LCMSTransform.java +++ b/src/java.desktop/share/classes/sun/java2d/cmm/lcms/LCMSTransform.java @@ -127,19 +127,15 @@ final class LCMSTransform implements ColorTransform { } /** - * Returns {@code true} if lcms may supports this format directly. + * Returns {@code true} if lcms may support this format directly. */ private static boolean isLCMSSupport(BufferedImage src, BufferedImage dst) { - if (!dst.getColorModel().hasAlpha()) { - return true; - } - // lcms as of now does not support pre-alpha - if (src.isAlphaPremultiplied() || dst.isAlphaPremultiplied()) { - return false; - } + boolean dstAlpha = dst.getColorModel().hasAlpha(); + boolean srcAlpha = src.getColorModel().hasAlpha(); + boolean srcPre = srcAlpha && src.getColorModel().isAlphaPremultiplied(); + // lcms does not convert pre-alpha for transparent src if dst is opaque // lcms does not set correct alpha for transparent dst if src is opaque - // is it feature or bug? - return dst.getColorModel().hasAlpha() == src.getColorModel().hasAlpha(); + return !dstAlpha && !srcPre || dstAlpha == srcAlpha; } public void colorConvert(BufferedImage src, BufferedImage dst) { @@ -424,9 +420,9 @@ final class LCMSTransform implements ColorTransform { public void colorConvert(Raster src, WritableRaster dst) { LCMSImageLayout srcIL, dstIL; - dstIL = LCMSImageLayout.createImageLayout(dst, false); + dstIL = LCMSImageLayout.createImageLayout(dst, null); if (dstIL != null) { - srcIL = LCMSImageLayout.createImageLayout(src, false); + srcIL = LCMSImageLayout.createImageLayout(src, null); if (srcIL != null) { doTransform(srcIL, dstIL); return; diff --git a/test/jdk/sun/java2d/cmm/ColorConvertOp/ColCvtAlphaDifferentSrcDst.java b/test/jdk/sun/java2d/cmm/ColorConvertOp/ColCvtAlphaDifferentSrcDst.java index 94a18b2a65b..31db9d1a380 100644 --- a/test/jdk/sun/java2d/cmm/ColorConvertOp/ColCvtAlphaDifferentSrcDst.java +++ b/test/jdk/sun/java2d/cmm/ColorConvertOp/ColCvtAlphaDifferentSrcDst.java @@ -23,11 +23,18 @@ import java.awt.AlphaComposite; import java.awt.Graphics2D; +import java.awt.Transparency; import java.awt.color.ColorSpace; import java.awt.color.ICC_ColorSpace; import java.awt.color.ICC_Profile; import java.awt.image.BufferedImage; import java.awt.image.ColorConvertOp; +import java.awt.image.ColorModel; +import java.awt.image.ComponentColorModel; +import java.awt.image.DataBuffer; +import java.awt.image.DirectColorModel; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; import static java.awt.image.BufferedImage.TYPE_3BYTE_BGR; import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR; @@ -45,7 +52,7 @@ import static java.awt.image.BufferedImage.TYPE_USHORT_GRAY; /* * @test - * @bug 8012229 8300725 + * @bug 8012229 8300725 8279216 * @summary one more test to check the alpha channel */ public final class ColCvtAlphaDifferentSrcDst { @@ -53,11 +60,19 @@ public final class ColCvtAlphaDifferentSrcDst { private static final int WIDTH = 256; private static final int HEIGHT = 256; + private static final int TYPE_CUSTOM_4BYTE_ABGR_PRE = -1; + private static final int TYPE_CUSTOM_4BYTE_ARGB_PRE = -2; + private static final int TYPE_CUSTOM_4BYTE_RGBA_PRE = -3; + private static final int TYPE_CUSTOM_4BYTE_GABR_PRE = -4; + private static final int TYPE_CUSTOM_INT_ARGB_PRE = -5; + private static final int TYPE_CUSTOM_INT_GABR_PRE = -6; + public static void main(String[] args) throws Exception { differentToOpaqueDst(); differentToTransparentDst(TYPE_INT_ARGB); differentToTransparentDst(TYPE_4BYTE_ABGR); differentToTransparentDst(TYPE_INT_ARGB_PRE); + differentToTransparentDst(TYPE_4BYTE_ABGR_PRE); differentToNullDst(); } @@ -97,7 +112,16 @@ public final class ColCvtAlphaDifferentSrcDst { opaqueDst(TYPE_INT_ARGB, TYPE_INT_BGR); opaqueDst(TYPE_4BYTE_ABGR, TYPE_INT_BGR); - // It is unclear how to hangle pre colors in the opaque DST + // compare the "fast" and "slow" paths + opaqueDst(TYPE_4BYTE_ABGR_PRE, TYPE_CUSTOM_4BYTE_ABGR_PRE); + opaqueDst(TYPE_4BYTE_ABGR_PRE, TYPE_CUSTOM_4BYTE_ARGB_PRE); + opaqueDst(TYPE_4BYTE_ABGR_PRE, TYPE_CUSTOM_4BYTE_RGBA_PRE); + opaqueDst(TYPE_4BYTE_ABGR_PRE, TYPE_CUSTOM_4BYTE_GABR_PRE); + + opaqueDst(TYPE_INT_ARGB_PRE, TYPE_CUSTOM_INT_ARGB_PRE); + opaqueDst(TYPE_INT_ARGB_PRE, TYPE_CUSTOM_INT_GABR_PRE); + + // It is unclear how to handle pre colors in the opaque DST //opaqueDst(TYPE_INT_ARGB_PRE, TYPE_4BYTE_ABGR_PRE); //opaqueDst(TYPE_4BYTE_ABGR_PRE, TYPE_INT_BGR); } @@ -196,7 +220,15 @@ public final class ColCvtAlphaDifferentSrcDst { } private static BufferedImage createSrc(int type) { - BufferedImage img = new BufferedImage(WIDTH, HEIGHT, type); + BufferedImage img = switch (type) { + case TYPE_CUSTOM_4BYTE_ABGR_PRE -> TYPE_4BYTE_ABGR_PRE(); + case TYPE_CUSTOM_4BYTE_ARGB_PRE -> TYPE_4BYTE_ARGB_PRE(); + case TYPE_CUSTOM_4BYTE_RGBA_PRE -> TYPE_4BYTE_RGBA_PRE(); + case TYPE_CUSTOM_4BYTE_GABR_PRE -> TYPE_4BYTE_GABR_PRE(); + case TYPE_CUSTOM_INT_ARGB_PRE -> TYPE_INT_ARGB_PRE(); + case TYPE_CUSTOM_INT_GABR_PRE -> TYPE_INT_GABR_PRE(); + default -> new BufferedImage(WIDTH, HEIGHT, type); + }; fill(img); return img; } @@ -220,4 +252,92 @@ public final class ColCvtAlphaDifferentSrcDst { } } } + + private static BufferedImage TYPE_4BYTE_RGBA_PRE() { + ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); + int[] nBits = {8, 8, 8, 8}; + int[] bOffs = {0, 1, 2, 3}; + ColorModel colorModel = new ComponentColorModel(cs, nBits, true, true, + Transparency.TRANSLUCENT, + DataBuffer.TYPE_BYTE); + WritableRaster raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, + WIDTH, HEIGHT, + WIDTH * 4, 4, + bOffs, null); + return new BufferedImage(colorModel, raster, true, null); + } + + private static BufferedImage TYPE_4BYTE_ABGR_PRE() { + ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); + int[] nBits = {8, 8, 8, 8}; + int[] bOffs = {3, 2, 1, 0}; + ColorModel colorModel = new ComponentColorModel(cs, nBits, true, true, + Transparency.TRANSLUCENT, + DataBuffer.TYPE_BYTE); + WritableRaster raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, + WIDTH, HEIGHT, + WIDTH * 4, 4, + bOffs, null); + return new BufferedImage(colorModel, raster, true, null); + } + + private static BufferedImage TYPE_4BYTE_ARGB_PRE() { + ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); + int[] nBits = {8, 8, 8, 8}; + int[] bOffs = {1, 2, 3, 0}; + ColorModel colorModel = new ComponentColorModel(cs, nBits, true, true, + Transparency.TRANSLUCENT, + DataBuffer.TYPE_BYTE); + WritableRaster raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, + WIDTH, HEIGHT, + WIDTH * 4, 4, + bOffs, null); + return new BufferedImage(colorModel, raster, true, null); + } + + private static BufferedImage TYPE_4BYTE_GABR_PRE() { + ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); + int[] nBits = {8, 8, 8, 8}; + int[] bOffs = {3, 0, 2, 1}; + ColorModel colorModel = new ComponentColorModel(cs, nBits, true, false, + Transparency.TRANSLUCENT, + DataBuffer.TYPE_BYTE); + WritableRaster raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, + WIDTH, HEIGHT, + WIDTH * 4, 4, + bOffs, null); + return new BufferedImage(colorModel, raster, true, null); + } + + private static BufferedImage TYPE_INT_ARGB_PRE() { + ColorModel colorModel = new DirectColorModel( + ColorSpace.getInstance(ColorSpace.CS_sRGB), + 32, + 0x00ff0000, // Red + 0x0000ff00, // Green + 0x000000ff, // Blue + 0xff000000, // Alpha + true, // Alpha Premultiplied + DataBuffer.TYPE_INT + ); + WritableRaster raster = colorModel.createCompatibleWritableRaster(WIDTH, + HEIGHT); + return new BufferedImage(colorModel, raster, true, null); + } + + private static BufferedImage TYPE_INT_GABR_PRE() { + ColorModel colorModel = new DirectColorModel( + ColorSpace.getInstance(ColorSpace.CS_sRGB), + 32, + 0x000000ff, // Red + 0xff000000, // Green + 0x0000ff00, // Blue + 0x00ff0000, // Alpha + true, // Alpha Premultiplied + DataBuffer.TYPE_INT + ); + WritableRaster raster = colorModel.createCompatibleWritableRaster(WIDTH, + HEIGHT); + return new BufferedImage(colorModel, raster, true, null); + } } diff --git a/test/jdk/sun/java2d/cmm/ColorConvertOp/PremultipliedAlpha.java b/test/jdk/sun/java2d/cmm/ColorConvertOp/PremultipliedAlpha.java new file mode 100644 index 00000000000..08e072cdb77 --- /dev/null +++ b/test/jdk/sun/java2d/cmm/ColorConvertOp/PremultipliedAlpha.java @@ -0,0 +1,264 @@ +/* + * Copyright Amazon.com Inc. 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.AlphaComposite; +import java.awt.Color; +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.ColorModel; +import java.awt.image.ComponentColorModel; +import java.awt.image.DataBuffer; +import java.awt.image.DirectColorModel; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java.util.Arrays; + +import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR_PRE; +import static java.awt.image.BufferedImage.TYPE_INT_ARGB_PRE; + +/** + * @test + * @bug 8279216 + * @summary Verifies implementation of premultiplied alpha + */ +public final class PremultipliedAlpha { + + private static final int SIZE = 256; + + private static final int COLOR_TOLERANCE = 2; + + private enum Type { + TYPE_ARGB_PRE, + TYPE_4BYTE_ABGR_PRE, + TYPE_CUSTOM_ARGB_PRE, + TYPE_CUSTOM_GABR_PRE, + TYPE_CUSTOM_4BYTE_ABGR_PRE, + TYPE_CUSTOM_4BYTE_ARGB_PRE, + TYPE_CUSTOM_4BYTE_RGBA_PRE, + TYPE_CUSTOM_4BYTE_GABR_PRE, + TYPE_CUSTOM_4USHORT_8bit_ARGB_PRE, + TYPE_CUSTOM_4INT_8bit_ARGB_PRE, + } + + private static final ColorSpace[] CSs = { + 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) + }; + + public static void main(String[] args) { + for (ColorSpace cs : CSs) { + for (Type dst : Type.values()) { + BufferedImage gold = null; + for (Type src : Type.values()) { + BufferedImage from = createSrc(src); + BufferedImage to = createDst(dst); + ColorConvertOp op = new ColorConvertOp(cs, null); + op.filter(from, to); + if (gold == null) { + gold = to; + } else { + validate(gold, to); + } + } + } + } + } + + private static void validate(BufferedImage img1, BufferedImage img2) { + for (int a = 0; a < SIZE; a++) { + for (int c = 0; c < SIZE; c++) { + int[] pixel1 = img1.getRaster().getPixel(c, a, (int[]) null); + int[] pixel2 = img2.getRaster().getPixel(c, a, (int[]) null); + if (pixel1.length != pixel2.length) { + throw new RuntimeException(); + } + for (int i = 0 ; i < pixel1.length; ++i) { + if (Math.abs(pixel1[i] - pixel2[i]) >= COLOR_TOLERANCE) { + System.out.println("c = " + c); + System.out.println("a = " + a); + System.err.println("rgb1 = " + Arrays.toString(pixel1)); + System.err.println("rgb2 = " + Arrays.toString(pixel2)); + throw new RuntimeException(); + } + } + } + } + } + + private static BufferedImage createDst(Type type) { + BufferedImage img = createSrc(type); + Graphics2D g = img.createGraphics(); + g.setComposite(AlphaComposite.Clear); + g.fillRect(0, 0, SIZE, SIZE); + g.dispose(); + return img; + } + + private static BufferedImage createSrc(Type type) { + BufferedImage bi = switch (type) { + case TYPE_ARGB_PRE -> new BufferedImage(SIZE, SIZE, TYPE_INT_ARGB_PRE); + case TYPE_CUSTOM_ARGB_PRE -> TYPE_ARGB_PRE(); + case TYPE_CUSTOM_GABR_PRE -> TYPE_GABR_PRE(); + case TYPE_4BYTE_ABGR_PRE -> new BufferedImage(SIZE, SIZE, TYPE_4BYTE_ABGR_PRE); + case TYPE_CUSTOM_4BYTE_ARGB_PRE -> TYPE_4BYTE_ARGB_PRE(); + case TYPE_CUSTOM_4BYTE_ABGR_PRE -> TYPE_4BYTE_ABGR_PRE(); + case TYPE_CUSTOM_4BYTE_RGBA_PRE -> TYPE_4BYTE_RGBA_PRE(); + case TYPE_CUSTOM_4BYTE_GABR_PRE -> TYPE_4BYTE_GABR_PRE(); + case TYPE_CUSTOM_4USHORT_8bit_ARGB_PRE -> TYPE_4USHORT_ARGB_8bit_PRE(); + case TYPE_CUSTOM_4INT_8bit_ARGB_PRE -> TYPE_4INT_ARGB_8bit_PRE(); + }; + fill(bi); + return bi; + } + + private static BufferedImage TYPE_ARGB_PRE() { + ColorModel colorModel = new DirectColorModel( + ColorSpace.getInstance(ColorSpace.CS_sRGB), + 32, + 0x00ff0000, // Red + 0x0000ff00, // Green + 0x000000ff, // Blue + 0xff000000, // Alpha + true, // Alpha Premultiplied + DataBuffer.TYPE_INT + ); + WritableRaster raster = colorModel.createCompatibleWritableRaster(SIZE, + SIZE); + return new BufferedImage(colorModel, raster, true, null); + } + + private static BufferedImage TYPE_GABR_PRE() { + ColorModel colorModel = new DirectColorModel( + ColorSpace.getInstance(ColorSpace.CS_sRGB), + 32, + 0x000000ff, // Red + 0xff000000, // Green + 0x0000ff00, // Blue + 0x00ff0000, // Alpha + true, // Alpha Premultiplied + DataBuffer.TYPE_INT + ); + WritableRaster raster = colorModel.createCompatibleWritableRaster(SIZE, + SIZE); + return new BufferedImage(colorModel, raster, true, null); + } + + private static BufferedImage TYPE_4BYTE_RGBA_PRE() { + ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); + int[] nBits = {8, 8, 8, 8}; + int[] bOffs = {0, 1, 2, 3}; + ColorModel colorModel = new ComponentColorModel(cs, nBits, true, true, + Transparency.TRANSLUCENT, + DataBuffer.TYPE_BYTE); + WritableRaster raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, + SIZE, SIZE, + SIZE * 4, 4, + bOffs, null); + return new BufferedImage(colorModel, raster, true, null); + } + + private static BufferedImage TYPE_4BYTE_ABGR_PRE() { + ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); + int[] nBits = {8, 8, 8, 8}; + int[] bOffs = {3, 2, 1, 0}; + ColorModel colorModel = new ComponentColorModel(cs, nBits, true, true, + Transparency.TRANSLUCENT, + DataBuffer.TYPE_BYTE); + WritableRaster raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, + SIZE, SIZE, + SIZE * 4, 4, + bOffs, null); + return new BufferedImage(colorModel, raster, true, null); + } + + private static BufferedImage TYPE_4BYTE_ARGB_PRE() { + ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); + int[] nBits = {8, 8, 8, 8}; + int[] bOffs = {1, 2, 3, 0}; + ColorModel colorModel = new ComponentColorModel(cs, nBits, true, true, + Transparency.TRANSLUCENT, + DataBuffer.TYPE_BYTE); + WritableRaster raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, + SIZE, SIZE, + SIZE * 4, 4, + bOffs, null); + return new BufferedImage(colorModel, raster, true, null); + } + + private static BufferedImage TYPE_4BYTE_GABR_PRE() { + ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); + int[] nBits = {8, 8, 8, 8}; + int[] bOffs = {3, 0, 2, 1}; + ColorModel colorModel = new ComponentColorModel(cs, nBits, true, false, + Transparency.TRANSLUCENT, + DataBuffer.TYPE_BYTE); + WritableRaster raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, + SIZE, SIZE, + SIZE * 4, 4, + bOffs, null); + return new BufferedImage(colorModel, raster, true, null); + } + + private static BufferedImage TYPE_4INT_ARGB_8bit_PRE() { + ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); + int[] nBits = {8, 8, 8, 8}; + ColorModel colorModel = new ComponentColorModel(cs, nBits, true, true, + Transparency.TRANSLUCENT, + DataBuffer.TYPE_INT); + WritableRaster raster = colorModel.createCompatibleWritableRaster(SIZE, + SIZE); + return new BufferedImage(colorModel, raster, true, null); + } + + private static BufferedImage TYPE_4USHORT_ARGB_8bit_PRE() { + ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); + int[] nBits = {8, 8, 8, 8}; + ColorModel colorModel = new ComponentColorModel(cs, nBits, true, true, + Transparency.TRANSLUCENT, + DataBuffer.TYPE_USHORT); + WritableRaster raster = colorModel.createCompatibleWritableRaster(SIZE, + SIZE); + return new BufferedImage(colorModel, raster, true, null); + } + + private static void fill(BufferedImage image) { +// Graphics2D g = image.createGraphics(); +// g.setComposite(AlphaComposite.Src); + for (int a = 0; a < SIZE; ++a) { + for (int c = 0; c < SIZE; ++c) { + Color c1 = new Color(a, c, c, a); +// g.setColor(c1); +//TODO CANNOT USE fillrect, does not work for custom types! +// g.fillRect(c, a, 1, 1); + image.setRGB(c,a , c1.getRGB()); + } + } +// g.dispose(); + } +} diff --git a/test/jdk/sun/java2d/cmm/ColorConvertOp/SkipSampleModel.java b/test/jdk/sun/java2d/cmm/ColorConvertOp/SkipSampleModel.java new file mode 100644 index 00000000000..75609634d1b --- /dev/null +++ b/test/jdk/sun/java2d/cmm/ColorConvertOp/SkipSampleModel.java @@ -0,0 +1,83 @@ +/* + * Copyright Amazon.com Inc. 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.ColorSpace; +import java.awt.image.BufferedImage; +import java.awt.image.ColorConvertOp; +import java.awt.image.SampleModel; + +/** + * @test + * @bug 8279216 + * @summary behavior checked by this test is not specified, this test just + * defends against accidental changes + */ +public final class SkipSampleModel { + + private static int[] TYPES = { + BufferedImage.TYPE_INT_RGB, + BufferedImage.TYPE_INT_ARGB, + BufferedImage.TYPE_INT_ARGB_PRE, + BufferedImage.TYPE_INT_BGR, + BufferedImage.TYPE_3BYTE_BGR, + BufferedImage.TYPE_4BYTE_ABGR, + BufferedImage.TYPE_4BYTE_ABGR_PRE, + BufferedImage.TYPE_USHORT_565_RGB, + BufferedImage.TYPE_USHORT_555_RGB, + BufferedImage.TYPE_BYTE_GRAY, + BufferedImage.TYPE_USHORT_GRAY, + BufferedImage.TYPE_BYTE_BINARY, + BufferedImage.TYPE_BYTE_INDEXED + }; + + private static final ColorSpace[] CSs = { + 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) + }; + + public static void main(String[] args) { + for (ColorSpace cs : CSs) { + ColorConvertOp op = new ColorConvertOp(cs, null); + for (int srcType : TYPES) { + for (int dstType : TYPES) { + BufferedImage src = new BufferedImage(1, 1, srcType) { + @Override + public SampleModel getSampleModel() { + throw new AssertionError(); + } + }; + BufferedImage dst = new BufferedImage(1, 1, dstType) { + @Override + public SampleModel getSampleModel() { + throw new AssertionError(); + } + }; + op.filter(src, dst); + } + } + } + } +}