From 730c13bf3ea9183901518027fe69209ab4fd0f08 Mon Sep 17 00:00:00 2001 From: jeremy Date: Tue, 6 May 2025 22:45:27 -0400 Subject: [PATCH 1/3] 8356320: fix tpix when we flood-fill a rect and tpix changes index In this ticket the problem was: `tpix` was the transparent pixel index of the current `model`. However `decoder.saved_image` uses its own IndexColorModel (see `decoder.saved_model`). In a simple gif these two models are the same, but in this case the gif has some frames that change the transparent pixel index between frames. We were filling the wrong tpix value, resulting in an opaque rectangle. --- .../sun/awt/image/GifImageDecoder.java | 1 + .../image/gif/bug8356320/GifErasureTest.java | 139 ++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 test/jdk/sun/awt/image/gif/bug8356320/GifErasureTest.java diff --git a/src/java.desktop/share/classes/sun/awt/image/GifImageDecoder.java b/src/java.desktop/share/classes/sun/awt/image/GifImageDecoder.java index df7167c1dd3ea..5d3f6b4b2287b 100644 --- a/src/java.desktop/share/classes/sun/awt/image/GifImageDecoder.java +++ b/src/java.desktop/share/classes/sun/awt/image/GifImageDecoder.java @@ -730,6 +730,7 @@ public boolean dispose() { // clear saved_image using transparent pixels // this will be used as the background in the next display if( decoder.saved_image != null ) { + tpix = (byte) decoder.saved_model.getTransparentPixel(); for( int i = 0; i < global_width * global_height; i ++ ) decoder.saved_image[i] = tpix; } diff --git a/test/jdk/sun/awt/image/gif/bug8356320/GifErasureTest.java b/test/jdk/sun/awt/image/gif/bug8356320/GifErasureTest.java new file mode 100644 index 0000000000000..2bb31545010a7 --- /dev/null +++ b/test/jdk/sun/awt/image/gif/bug8356320/GifErasureTest.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2025, 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 8356320 + * @summary This test verifies that we enforce the transparent background + * when the disposal code is DISPOSAL_BGCOLOR and the transparent pixel + * index changes. + */ + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Toolkit; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.ImageConsumer; +import java.awt.image.IndexColorModel; +import java.net.URL; +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.concurrent.Semaphore; + +public class GifErasureTest { + public static void main(String[] args) throws Exception { + URL srcURL = GifErasureTest.class.getResource("leo.gif"); + BufferedImage[] frames = getFrames(srcURL, 3); + + if (new Color(frames[2].getRGB(20, 20), true).getAlpha() != 0) { + throw new Error("The pixel at (20, 20) should be transparent."); + } + } + + private static BufferedImage[] getFrames(URL gifURL, int numberOfFrames) { + Image image = Toolkit.getDefaultToolkit().createImage(gifURL); + ArrayList returnValue = new ArrayList<>(numberOfFrames); + + Semaphore semaphore = new Semaphore(1); + semaphore.acquireUninterruptibly(); + image.getSource().startProduction(new ImageConsumer() { + BufferedImage bi; + int frameCtr = 0; + + @Override + public void setDimensions(int width, int height) { + bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + } + + @Override + public void setProperties(Hashtable props) {} + + @Override + public void setColorModel(ColorModel model) {} + + @Override + public void setHints(int hintflags) {} + + @Override + public void setPixels(int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize) { + try { + final int yMax = y + h; + final int xMax = x + w; + + IndexColorModel icm = (IndexColorModel) model; + int[] colorModelRGBs = new int[icm.getMapSize()]; + icm.getRGBs(colorModelRGBs); + int[] argbRow = new int[bi.getWidth()]; + + for (int y_ = y; y_ < yMax; y_++) { + int i = y_ * scansize + off; + for (int x_ = x; x_ < xMax; x_++, i++) { + int pixel = pixels[i] & 0xff; + argbRow[x_ - x] = colorModelRGBs[pixel]; + } + bi.getRaster().setDataElements(x, y_, w, 1, argbRow); + } + } catch (RuntimeException e) { + // we don't expect this to happen, but if something goes + // wrong nobody else will print our stacktrace for us: + e.printStackTrace(); + throw e; + } + } + + @Override + public void setPixels(int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize) {} + + @Override + public void imageComplete(int status) { + try { + frameCtr++; + + BufferedImage copy = new BufferedImage(bi.getWidth(), + bi.getHeight(), BufferedImage.TYPE_INT_ARGB); + Graphics2D g = copy.createGraphics(); + g.drawImage(bi, 0, 0, null); + g.dispose(); + returnValue.add(copy); + + if (frameCtr == numberOfFrames) { + semaphore.release(); + // if we don't detach this consumer the producer will + // loop forever + image.getSource().removeConsumer(this); + image.flush(); + } + } catch(Exception e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + }); + + semaphore.acquireUninterruptibly(); + + return returnValue.toArray(new BufferedImage[0]); + } +} From 4bfe482f32b4378833d21ea33125d7cdd11dd61a Mon Sep 17 00:00:00 2001 From: jeremy Date: Tue, 6 May 2025 22:45:49 -0400 Subject: [PATCH 2/3] 8356320: adding resource leo.gif --- test/jdk/sun/awt/image/gif/bug8356320/leo.gif | Bin 0 -> 5737 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/jdk/sun/awt/image/gif/bug8356320/leo.gif diff --git a/test/jdk/sun/awt/image/gif/bug8356320/leo.gif b/test/jdk/sun/awt/image/gif/bug8356320/leo.gif new file mode 100644 index 0000000000000000000000000000000000000000..df56231813993a5541356b2041f126717ed835bf GIT binary patch literal 5737 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 literal 0 HcmV?d00001 From da529dcdfe19840a91346ab904ff913453961827 Mon Sep 17 00:00:00 2001 From: jeremy Date: Tue, 6 May 2025 22:53:19 -0400 Subject: [PATCH 3/3] 8356137: updating (c) year --- .../share/classes/sun/awt/image/GifImageDecoder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.desktop/share/classes/sun/awt/image/GifImageDecoder.java b/src/java.desktop/share/classes/sun/awt/image/GifImageDecoder.java index 5d3f6b4b2287b..f689804103faf 100644 --- a/src/java.desktop/share/classes/sun/awt/image/GifImageDecoder.java +++ b/src/java.desktop/share/classes/sun/awt/image/GifImageDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2025, 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