| /* |
| * Copyright (c) 2016, 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 6334602 |
| * @summary Test verifies that when we create GIF image from Opaque PNG images |
| * it should not be transparent. |
| * @modules java.desktop/com.sun.imageio.plugins.gif |
| * @run main/manual OpaquePNGToGIFTest |
| */ |
| |
| import java.awt.image.BufferedImage; |
| import com.sun.imageio.plugins.gif.GIFImageMetadata; |
| import java.awt.Canvas; |
| import java.awt.Color; |
| import java.awt.Dimension; |
| import java.awt.Frame; |
| import java.awt.Graphics; |
| import java.awt.Graphics2D; |
| import java.awt.GridBagConstraints; |
| import java.awt.GridBagLayout; |
| import java.awt.Image; |
| import java.awt.Toolkit; |
| import java.awt.event.ActionEvent; |
| import java.awt.event.ActionListener; |
| import java.awt.event.WindowAdapter; |
| import java.awt.event.WindowEvent; |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.nio.file.Files; |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| import javax.imageio.IIOImage; |
| import javax.imageio.ImageIO; |
| import javax.imageio.ImageReader; |
| import javax.imageio.ImageTypeSpecifier; |
| import javax.imageio.ImageWriteParam; |
| import javax.imageio.ImageWriter; |
| import javax.imageio.metadata.IIOMetadata; |
| import javax.imageio.stream.ImageInputStream; |
| import javax.imageio.stream.ImageOutputStream; |
| import javax.swing.JButton; |
| import javax.swing.JDialog; |
| import javax.swing.JLabel; |
| import javax.swing.JPanel; |
| import javax.swing.SwingUtilities; |
| |
| public final class OpaquePNGToGIFTest extends Frame { |
| |
| Image img = null; |
| private Dimension prefImgSize = new Dimension(100, 100); |
| private Color canvasColor = new Color(0, 255, 0); |
| File outputFile = null; |
| ImageCanvas imageCanvas = new ImageCanvas(); |
| FileOutputStream fos; |
| private static GridBagLayout layout; |
| private static JPanel mainControlPanel; |
| private static JPanel resultButtonPanel; |
| private static JPanel canvasPanel; |
| private static JLabel instructionText; |
| private static JButton startTestButton; |
| private static JButton passButton; |
| private static JButton failButton; |
| private static JDialog dialog; |
| private static Frame instructionFrame; |
| private static Frame imageFrame; |
| Toolkit tk; |
| ImageWriter writer = null; |
| boolean testPassed, testGeneratedInterrupt, startButtonClicked; |
| private static Thread mainThread; |
| |
| public OpaquePNGToGIFTest() throws Exception { |
| SwingUtilities.invokeAndWait(() -> { |
| try { |
| startTest(); |
| } catch (Exception ex) { |
| Logger.getLogger(OpaquePNGToGIFTest.class.getName()). |
| log(Level.SEVERE, null, ex); |
| } |
| }); |
| mainThread = Thread.currentThread(); |
| try { |
| Thread.sleep(60000); |
| } catch (InterruptedException e) { |
| if (!testPassed && testGeneratedInterrupt) { |
| throw new RuntimeException("Test failed or didnt run" |
| + " properly"); |
| } |
| } |
| if (!testGeneratedInterrupt) { |
| if (img != null) { |
| img.flush(); |
| } |
| instructionFrame.dispose(); |
| if (startButtonClicked) { |
| imageFrame.dispose(); |
| } |
| fos.close(); |
| Files.delete(outputFile.toPath()); |
| throw new RuntimeException("user has not executed the test"); |
| } |
| } |
| |
| public void startTest() throws Exception { |
| instructionFrame = new Frame(); |
| dialog = new JDialog(instructionFrame); |
| dialog.setTitle("Instruction Dialog"); |
| layout = new GridBagLayout(); |
| mainControlPanel = new JPanel(layout); |
| resultButtonPanel = new JPanel(layout); |
| canvasPanel = new JPanel(); |
| GridBagConstraints gbc = new GridBagConstraints(); |
| String instructions |
| = "<html> INSTRUCTIONS:<br><br>" |
| + "After clicking on Start Test button you will see Red<br> " |
| + " circle drawn with light blue background, if the circle<br>" |
| + " color changes from Red to Green then press button Fail,<br>" |
| + " if it stays Red then press button Pass.<br><br></html>"; |
| instructionText = new JLabel(); |
| instructionText.setText(instructions); |
| |
| gbc.gridx = 0; |
| gbc.gridy = 0; |
| gbc.fill = GridBagConstraints.HORIZONTAL; |
| mainControlPanel.add(instructionText, gbc); |
| startTestButton = new JButton("Start Test"); |
| startTestButton.setActionCommand("Start Test"); |
| startTestButton.addActionListener(new ActionListener() { |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| try { |
| startButtonClicked = true; |
| imageFrame = new Frame(); |
| |
| Iterator it = ImageIO.getImageWritersByFormatName("GIF"); |
| while (it.hasNext()) { |
| writer = (ImageWriter) it.next(); |
| break; |
| } |
| // read input opaque PNG image. |
| String fileName = "opaque_input.png"; |
| String sep = System.getProperty("file.separator"); |
| String dir = System.getProperty("test.src", "."); |
| System.out.println(dir + " " + sep); |
| String filePath = dir + sep + fileName; |
| File inputFile = new File(filePath); |
| ImageInputStream iis = ImageIO. |
| createImageInputStream(inputFile); |
| ImageReader reader = null; |
| Iterator readerIter = ImageIO.getImageReaders(iis); |
| while (readerIter.hasNext()) { |
| reader = (ImageReader) readerIter.next(); |
| break; |
| } |
| |
| reader.setInput(iis); |
| IIOMetadata imgData = reader.getImageMetadata(0); |
| BufferedImage bi = reader.read(0); |
| |
| //create temporary GIF imageas output |
| File directory = new File(dir + sep); |
| outputFile = File.createTempFile("output", |
| ".gif", directory); |
| createAnimatedImage(bi, imgData, |
| writer, outputFile); |
| writer.dispose(); |
| iis.close(); |
| if (outputFile == null) { |
| throw new RuntimeException("Unable to create output GIF" |
| + " file"); |
| } |
| // extract GIF image using Toolkit and show it on a Panel. |
| tk = Toolkit.getDefaultToolkit(); |
| img = tk.getImage(dir + sep + outputFile.getName()); |
| directory.delete(); |
| imageCanvas.setBackground(canvasColor); |
| imageCanvas.setImage(img); |
| imageCanvas.setPreferredSize(prefImgSize); |
| canvasPanel.doLayout(); |
| |
| canvasPanel.add(imageCanvas); |
| imageFrame.add("Center", canvasPanel); |
| imageFrame.setSize(200, 200); |
| imageFrame.setVisible(true); |
| imageFrame.addWindowListener(new WindowAdapter() { |
| @Override |
| public void windowClosing(WindowEvent e) { |
| try { |
| img.flush(); |
| instructionFrame.dispose(); |
| imageFrame.dispose(); |
| fail(); |
| } finally { |
| try { |
| fos.close(); |
| Files.delete(outputFile.toPath()); |
| } catch (IOException ex) { |
| Logger.getLogger(OpaquePNGToGIFTest.class. |
| getName()).log(Level.SEVERE, null, |
| ex); |
| } |
| } |
| } |
| }); |
| } catch (IOException ex) { |
| Logger.getLogger(OpaquePNGToGIFTest.class.getName()). |
| log(Level.SEVERE, null, ex); |
| } |
| } |
| }); |
| passButton = new JButton("Pass"); |
| passButton.setActionCommand("Pass"); |
| passButton.addActionListener(new ActionListener() { |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| try { |
| if (img != null) { |
| img.flush(); |
| } |
| instructionFrame.dispose(); |
| if (!startButtonClicked) { |
| fail(); |
| } else { |
| imageFrame.dispose(); |
| pass(); |
| } |
| } finally { |
| try { |
| fos.close(); |
| Files.delete(outputFile.toPath()); |
| } catch (IOException ex) { |
| Logger.getLogger(OpaquePNGToGIFTest.class. |
| getName()).log(Level.SEVERE, null, ex); |
| } |
| } |
| } |
| }); |
| failButton = new JButton("Fail"); |
| failButton.setActionCommand("Fail"); |
| failButton.addActionListener(new ActionListener() { |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| try { |
| if (img != null) { |
| img.flush(); |
| } |
| instructionFrame.dispose(); |
| if (!startButtonClicked) { |
| fail(); |
| } else { |
| imageFrame.dispose(); |
| fail(); |
| } |
| } finally { |
| try { |
| fos.close(); |
| Files.delete(outputFile.toPath()); |
| } catch (IOException ex) { |
| Logger.getLogger(OpaquePNGToGIFTest.class. |
| getName()).log(Level.SEVERE, null, ex); |
| } |
| } |
| } |
| }); |
| gbc.gridx = 1; |
| gbc.gridy = 0; |
| resultButtonPanel.add(startTestButton, gbc); |
| gbc.gridx = 2; |
| gbc.gridy = 0; |
| resultButtonPanel.add(passButton, gbc); |
| gbc.gridx = 3; |
| gbc.gridy = 0; |
| resultButtonPanel.add(failButton, gbc); |
| |
| gbc.gridx = 0; |
| gbc.gridy = 1; |
| mainControlPanel.add(resultButtonPanel, gbc); |
| |
| dialog.add(mainControlPanel); |
| dialog.setSize(400, 200); |
| dialog.setLocationRelativeTo(null); |
| dialog.setVisible(true); |
| |
| dialog.addWindowListener(new WindowAdapter() { |
| @Override |
| public void windowClosing(WindowEvent e) { |
| try { |
| if (img != null) { |
| img.flush(); |
| } |
| instructionFrame.dispose(); |
| if (!startButtonClicked) { |
| fail(); |
| } else { |
| imageFrame.dispose(); |
| fail(); |
| } |
| } finally { |
| try { |
| fos.close(); |
| Files.delete(outputFile.toPath()); |
| } catch (IOException ex) { |
| Logger.getLogger(OpaquePNGToGIFTest.class. |
| getName()).log(Level.SEVERE, null, ex); |
| } |
| } |
| } |
| }); |
| } |
| |
| public synchronized void pass() { |
| testPassed = true; |
| testGeneratedInterrupt = true; |
| mainThread.interrupt(); |
| } |
| |
| public synchronized void fail() { |
| testPassed = false; |
| testGeneratedInterrupt = true; |
| mainThread.interrupt(); |
| } |
| |
| public void createAnimatedImage(BufferedImage bi, IIOMetadata metadata, |
| ImageWriter writer, File outputFile) { |
| try { |
| |
| fos = new FileOutputStream(outputFile); |
| ImageOutputStream ios = ImageIO.createImageOutputStream(fos); |
| System.out.println(ios); |
| writer.setOutput(ios); |
| |
| ImageWriteParam param = writer.getDefaultWriteParam(); |
| IIOMetadata streamData = writer.getDefaultStreamMetadata(param); |
| |
| writer.prepareWriteSequence(streamData); |
| ImageTypeSpecifier specify = new ImageTypeSpecifier(bi); |
| IIOMetadata imgData = writer.convertImageMetadata( |
| (IIOMetadata) metadata, specify, param); |
| GIFImageMetadata gifData = setAnimationProperties(imgData); |
| IIOImage iim = new IIOImage(bi, null, gifData); |
| param.setProgressiveMode(param.MODE_DISABLED); |
| writer.writeToSequence(iim, param); |
| writer.endWriteSequence(); |
| ios.close(); |
| } catch (Exception e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| public GIFImageMetadata setAnimationProperties(IIOMetadata data) { |
| ArrayList appIDs = new ArrayList(); |
| appIDs.add(new String("NETSCAPE").getBytes()); |
| ArrayList authCodes = new ArrayList(); |
| authCodes.add(new String("2.0").getBytes()); |
| ArrayList appData = new ArrayList(); |
| byte[] authData = {1, 0, 0}; |
| appData.add(authData); |
| |
| GIFImageMetadata gifData = (GIFImageMetadata) data; |
| gifData.delayTime = 200; |
| // If we set disposalMethod to 2 then only the issue is reproduced. |
| gifData.disposalMethod = 2; |
| gifData.userInputFlag = false; |
| |
| gifData.applicationIDs = appIDs; |
| gifData.authenticationCodes = authCodes; |
| gifData.applicationData = appData; |
| |
| return gifData; |
| } |
| |
| public static void main(String args[]) throws Exception { |
| OpaquePNGToGIFTest test = new OpaquePNGToGIFTest(); |
| } |
| |
| class ImageCanvas extends Canvas { |
| |
| Image im = null; |
| |
| public void setImage(Image img) { |
| im = img; |
| } |
| |
| public void clearImage() { |
| im = null; |
| repaint(); |
| } |
| |
| public void paint(Graphics g) { |
| Graphics2D g2d = (Graphics2D) g; |
| |
| if (im != null) { |
| g2d.drawImage(im, 1, 1, getWidth(), getHeight(), this); |
| } |
| } |
| } |
| } |
| |