test/jdk/java/awt/image/OpaquePNGToGIFTest.java
author ihse
Tue, 22 Oct 2019 09:51:52 +0200
branchihse-cflags-rewrite-branch
changeset 58736 e878a0b7cff0
parent 47216 71c04702a3d5
permissions -rw-r--r--
Add doubunder on solaris in two places.

/*
 * 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);
            }
        }
    }
}