From 828bd843c503a1d11305d413556a0f7d213a756a Mon Sep 17 00:00:00 2001 From: prrace Date: Fri, 20 Sep 2024 09:56:45 -0700 Subject: [PATCH] 8340411 --- .../image/BytePackedRaster/DitherTest.java | 147 ++++++++++++++++++ .../awt/image/BytePackedRaster/MultiOp.java | 108 +++++++++++++ .../ByteBinaryBitmask.java | 88 +++++++++++ .../ImageRepresentation/CustomSourceCM.java | 142 +++++++++++++++++ 4 files changed, 485 insertions(+) create mode 100644 test/jdk/sun/awt/image/BytePackedRaster/DitherTest.java create mode 100644 test/jdk/sun/awt/image/BytePackedRaster/MultiOp.java create mode 100644 test/jdk/sun/awt/image/ImageRepresentation/ByteBinaryBitmask.java create mode 100644 test/jdk/sun/awt/image/ImageRepresentation/CustomSourceCM.java diff --git a/test/jdk/sun/awt/image/BytePackedRaster/DitherTest.java b/test/jdk/sun/awt/image/BytePackedRaster/DitherTest.java new file mode 100644 index 0000000000000..29b42b49fe778 --- /dev/null +++ b/test/jdk/sun/awt/image/BytePackedRaster/DitherTest.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 1999, 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. + */ + +/* + * @test + * @bug 4184283 + * @summary Checks rendering of dithered byte packed image does not crash. + */ + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.IndexColorModel; +import java.awt.image.MemoryImageSource; +import java.awt.image.WritableRaster; + +public class DitherTest extends Component { + + final static int NOOP = 0; + final static int RED = 1; + final static int GREEN = 2; + final static int BLUE = 3; + final static int ALPHA = 4; + final static int SATURATION = 5; + + final static byte red[] = {(byte)0, (byte)132, (byte)0, (byte)132, (byte)0, (byte)132, + (byte)0, (byte)198, (byte)198, (byte)165, (byte)255, (byte)165, (byte)132, + (byte)255, (byte)0, (byte)255}; + + final static byte green[] = {(byte)0, (byte)0, (byte)130, (byte)130, (byte)0, + (byte)0, (byte)130, (byte)195, (byte)223, (byte)203, (byte)251, (byte)162, + (byte)132, (byte)0, (byte)255, (byte)255}; + + final static byte blue[] = {(byte)0, (byte)0, (byte)0, (byte)0, (byte)132, (byte)132, + (byte)132, (byte)198, (byte)198, (byte)247, (byte)247, (byte)165, (byte)132, + (byte)0, (byte)0, (byte)0}; + + static IndexColorModel cm16 = new IndexColorModel( 4, 16, red, green, blue); + + + public static void main(String args[]) { + + int imageWidth = 256; + int imageHeight = 256; + WritableRaster raster = cm16.createCompatibleWritableRaster(imageWidth, imageHeight); + BufferedImage intermediateImage = new BufferedImage(cm16, raster, false, null); + Image calculatedImage = calculateImage(); + + Graphics2D ig = intermediateImage.createGraphics(); + // Clear background and fill a red rectangle just to prove that we can draw on intermediateImage + ig.setColor(Color.white); + ig.fillRect(0,0,imageWidth,imageHeight); + ig.drawImage(calculatedImage, 0, 0, imageWidth, imageHeight, null); + ig.setColor(Color.red); + ig.fillRect(0,0,5,5); + + BufferedImage destImage = new BufferedImage(imageWidth, imageWidth, BufferedImage.TYPE_INT_RGB); + Graphics2D dg = destImage.createGraphics(); + dg.drawImage(intermediateImage, 0, 0, imageWidth, imageHeight, null); + } + + private static void applymethod(int c[], int method, int step, int total, int vals[]) { + if (method == NOOP) + return; + int val = ((total < 2) + ? vals[0] + : vals[0] + ((vals[1] - vals[0]) * step / (total - 1))); + switch (method) { + case RED: + c[0] = val; + break; + case GREEN: + c[1] = val; + break; + case BLUE: + c[2] = val; + break; + case ALPHA: + c[3] = val; + break; + case SATURATION: + int max = Math.max(Math.max(c[0], c[1]), c[2]); + int min = max * (255 - val) / 255; + if (c[0] == 0) c[0] = min; + if (c[1] == 0) c[1] = min; + if (c[2] == 0) c[2] = min; + break; + } + } + + private static Image calculateImage() { + + int xvals[] = { 0, 255 }; + int yvals[] = { 0, 255 }; + int xmethod = RED; + int ymethod = BLUE; + int width = 256; + int height = 256; + int pixels[] = new int[width * height]; + int c[] = new int[4]; + int index = 0; + for (int j = 0; j < height; j++) { + for (int i = 0; i < width; i++) { + c[0] = c[1] = c[2] = 0; + c[3] = 255; + if (xmethod < ymethod) { + applymethod(c, xmethod, i, width, xvals); + applymethod(c, ymethod, j, height, yvals); + } else { + applymethod(c, ymethod, j, height, yvals); + applymethod(c, xmethod, i, width, xvals); + } + pixels[index++] = ((c[3] << 24) | + (c[0] << 16) | + (c[1] << 8) | + (c[2] << 0)); + } + } + + DitherTest dt = new DitherTest(); + return dt.createImage(new MemoryImageSource(width, height, ColorModel.getRGBdefault(), pixels, 0, width)); + } +} + diff --git a/test/jdk/sun/awt/image/BytePackedRaster/MultiOp.java b/test/jdk/sun/awt/image/BytePackedRaster/MultiOp.java new file mode 100644 index 0000000000000..2c396792548f2 --- /dev/null +++ b/test/jdk/sun/awt/image/BytePackedRaster/MultiOp.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 1999, 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. + */ + +/* + * @test + * @bug 4213160 + * @summary Should generate a black image + */ + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.IndexColorModel; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java.awt.geom.AffineTransform; + +public class MultiOp { + + public static void main(String[] argv) { + + int width = 256; + int height = 256; + + int pixelBits = 2; // 1, 2, 4, or 8 + // 1 and 8 make the code throw ImagingOpException, 2 and 4 + // make the code SEGV on Sol. + + byte[] lut1Arr = new byte[] {0, (byte)255 }; + byte[] lut2Arr = new byte[] {0, (byte)85, (byte)170, (byte)255}; + byte[] lut4Arr = new byte[] {0, (byte)17, (byte)34, (byte)51, + (byte)68, (byte)85,(byte) 102, (byte)119, + (byte)136, (byte)153, (byte)170, (byte)187, + (byte)204, (byte)221, (byte)238, (byte)255}; + byte[] lut8Arr = new byte[256]; + for (int i = 0; i < 256; i++) { + lut8Arr[i] = (byte)i; + } + + // Create the binary image + int bytesPerRow = width * pixelBits / 8; + byte[] imageData = new byte[height * bytesPerRow]; + ColorModel cm = null; + + switch (pixelBits) { + case 1: + cm = new IndexColorModel(pixelBits, lut1Arr.length, + lut1Arr, lut1Arr, lut1Arr); + break; + case 2: + cm = new IndexColorModel(pixelBits, lut2Arr.length, + lut2Arr, lut2Arr, lut2Arr); + break; + case 4: + cm = new IndexColorModel(pixelBits, lut4Arr.length, + lut4Arr, lut4Arr, lut4Arr); + break; + case 8: + cm = new IndexColorModel(pixelBits, lut8Arr.length, + lut8Arr, lut8Arr, lut8Arr); + break; + default: + {new Exception("Invalid # of bit per pixel").printStackTrace();} + } + + DataBuffer db = new DataBufferByte(imageData, imageData.length); + WritableRaster r = Raster.createPackedRaster(db, width, height, + pixelBits, null); + BufferedImage srcImage = new BufferedImage(cm, r, false, null); + + BufferedImage destImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + Graphics2D g = destImage.createGraphics(); + AffineTransform af = AffineTransform.getScaleInstance(.5, .5); + // This draw image is the problem + g.drawImage(srcImage, af, null); + int blackPixel = Color.black.getRGB(); + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + if (destImage.getRGB(x, y) != blackPixel) { + throw new RuntimeException("Not black"); + } + } + } + } +} diff --git a/test/jdk/sun/awt/image/ImageRepresentation/ByteBinaryBitmask.java b/test/jdk/sun/awt/image/ImageRepresentation/ByteBinaryBitmask.java new file mode 100644 index 0000000000000..29a727b23d5ce --- /dev/null +++ b/test/jdk/sun/awt/image/ImageRepresentation/ByteBinaryBitmask.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 20002, 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. + */ + +/* + * @test + * @bug 4673490 + * @summary This test verifies that Toolkit images with a 1-bit + * IndexColorModel (known as ByteBinary) and a transparent index are rendered properly. + */ + +import java.awt.Color; +import java.awt.Graphics2D; + +import java.awt.image.BufferedImage; +import java.awt.image.IndexColorModel; + +public class ByteBinaryBitmask { + + public static void main(String argv[]) throws Exception { + + /* Create the image */ + int w = 16, h = 16; + byte[] bw = { (byte)255, (byte)0, }; + IndexColorModel icm = new IndexColorModel(1, 2, bw, bw, bw, 0); + BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_BINARY, icm); + Graphics2D g2d = img.createGraphics(); + g2d.setColor(Color.white); + g2d.fillRect(0, 0, w, h); + g2d.setColor(Color.black); + int xoff = 5; + g2d.fillRect(xoff, 5, 1, 10); // 1 pixel wide + + int dw = 200, dh = 50; + BufferedImage dest = new BufferedImage(dw, dh, BufferedImage.TYPE_INT_RGB); + Graphics2D g = dest.createGraphics(); + g.setColor(Color.green); + g.fillRect(0, 0, dw, dh); + int x1 = 10; + int x2 = 50; + int x3 = 90; + int x4 = 130; + g.drawImage(img, x1, 10, null); + g.drawImage(img, x2, 10, null); + g.drawImage(img, x3, 10, null); + g.drawImage(img, x4, 10, null); + + int blackPix = Color.black.getRGB(); + for (int y = 0; y < dh; y++) { + boolean isBlack = false; + for (int x = 0; x < dw; x++) { + int rgb = dest.getRGB(x, y); + if (rgb == blackPix) { + /* Src image has a one pixel wide vertical rect at off "xoff" and + * this is drawn at x1/x2/x3/x4) so the sum of those are the x locations + * to expect black. + */ + if (x != (x1 + xoff) && x != (x2 + xoff) && x != (x3 + xoff) && x!= (x4 + xoff)) { + throw new RuntimeException("wrong x location: " +x); + } + if (isBlack) { + throw new RuntimeException("black after black"); + } + } + isBlack = rgb == blackPix; + } + } + } +} diff --git a/test/jdk/sun/awt/image/ImageRepresentation/CustomSourceCM.java b/test/jdk/sun/awt/image/ImageRepresentation/CustomSourceCM.java new file mode 100644 index 0000000000000..c56b4ef88c807 --- /dev/null +++ b/test/jdk/sun/awt/image/ImageRepresentation/CustomSourceCM.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 1999, 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. + */ + +/** + * @test + * @bug 4192756 + * @summary Tests that using a non-default colormodel generates correct images under 16/24 bit mode + */ + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.DirectColorModel; +import java.awt.image.ComponentColorModel; +import java.awt.image.MemoryImageSource; +import java.util.Arrays; + +/* + * NOTE: This bug only appears under specific conditions. If the background of + * the surface is red, then you are not running under the conditions necessary + * to test for the regression so the results of this test will be inconclusive. + * + * The test should be run under any of the following screen depths/surfaces: + * + * 15-bit, otherwise known as 555 RGB or 32768 (thousands) colors + * 16-bit, otherwise known as 565 RGB or 65536 (thousands) colors + * 24-bit, otherwise known as 16777216 (millions) colors + * + * The test draws 2 rectangles. Both rectangles should be half black (left) + * and half blue (right). If the top rectangle is all black, the test fails. + * If the background is red, the results are inconclusive (see above). +*/ + +public class CustomSourceCM extends Component { + + public static int IMG_W = 80; + public static int IMG_H = 30; + + static void test(int imageType) { + + int w = IMG_W + 20; + int h = IMG_H * 2 + 40; + BufferedImage bi = new BufferedImage(w, h, imageType); + + DirectColorModel dcm; + + /* the next dozen lines or so are intended to help + * ascertain if the destination surface is of the type + * that exhibited the original bug, making the background + * white in those cases. It is not strictly necessary. + * It is only for a manual tester to be able to tell by looking. + * The real test is the check for black and blue later on. + */ + Graphics2D g = bi.createGraphics(); + g.setColor(Color.red); + g.fillRect(0, 0, w, h); + + ColorModel cm = bi.getColorModel(); + if (cm instanceof ComponentColorModel) { + g.setColor(Color.white); + g.fillRect(0, 0, w, h); + } else if (cm instanceof DirectColorModel) { + dcm = (DirectColorModel) cm; + if (dcm.getPixelSize() < 24) { + g.setColor(Color.white); + g.fillRect(0, 0, w, h); + } + } + + // Construct a ColorModel and data for a 16-bit 565 image... + dcm = new DirectColorModel(16, 0x1f, 0x7e0, 0xf800); + + // Create an image which is black on the left, blue on the right. + int[] pixels = new int[IMG_W * IMG_H]; + int blue = dcm.getBlueMask(); + int off = 0; + for (int y = 0; y < IMG_H; y++) { + Arrays.fill(pixels, off, off+IMG_W/2, 0); + Arrays.fill(pixels, off+IMG_W/2, off+IMG_W, blue); + off += IMG_W; + } + MemoryImageSource mis = new MemoryImageSource(IMG_W, IMG_H, dcm, + pixels, 0, IMG_W); + CustomSourceCM comp = new CustomSourceCM(); + Image img = comp.createImage(mis); + + // Draw the image on to the surface. + g.drawImage(img, 10, 10, null); + + // Create a similar effect with 2 fillrects, below the image. + g.setColor(Color.black); + g.fillRect(10, 60, IMG_W/2, IMG_H); + g.setColor(Color.blue); + g.fillRect(10+IMG_W/2, 60, IMG_W/2, IMG_H); + + // Now sample points in the image to confirm they are the expected color. + int bluePix = Color.blue.getRGB(); + int blackPix = Color.black.getRGB(); + int black_topLeft = bi.getRGB(10+IMG_W/4, 10+IMG_H/2); + int blue_topRight = bi.getRGB(10+IMG_W*3/4, 10+IMG_H/2); + int black_bottomLeft = bi.getRGB(10+IMG_W/4, 60+IMG_H/2); + int blue_bottomRight = bi.getRGB(10+IMG_W*3/4, 60+IMG_H/2); + if ((black_topLeft != blackPix) || (black_bottomLeft != blackPix) || + (blue_topRight != bluePix) || (blue_bottomRight != bluePix)) { + + String fileName = "failed " + imageType + ".png"; + try { + javax.imageio.ImageIO.write(bi, "png", new java.io.File(fileName)); + } catch (Exception e) { }; + throw new RuntimeException("unexpected colors"); + } + } + + public static void main(String argv[]) { + test(BufferedImage.TYPE_USHORT_555_RGB); + test(BufferedImage.TYPE_USHORT_565_RGB); + test(BufferedImage.TYPE_3BYTE_BGR); + } +}