3789983e89
Reviewed-by: darcy, ihse
423 lines
16 KiB
Java
423 lines
16 KiB
Java
/*
|
|
* 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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|