test/jdk/java/awt/image/OpaquePNGToGIFTest.java
changeset 47216 71c04702a3d5
parent 42217 53ac12e1344a
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24  /*
       
    25  * @test
       
    26  * @bug     6334602
       
    27  * @summary Test verifies that when we create GIF image from Opaque PNG images
       
    28  *          it should not be transparent.
       
    29  * @modules java.desktop/com.sun.imageio.plugins.gif
       
    30  * @run     main/manual OpaquePNGToGIFTest
       
    31  */
       
    32 
       
    33 import java.awt.image.BufferedImage;
       
    34 import com.sun.imageio.plugins.gif.GIFImageMetadata;
       
    35 import java.awt.Canvas;
       
    36 import java.awt.Color;
       
    37 import java.awt.Dimension;
       
    38 import java.awt.Frame;
       
    39 import java.awt.Graphics;
       
    40 import java.awt.Graphics2D;
       
    41 import java.awt.GridBagConstraints;
       
    42 import java.awt.GridBagLayout;
       
    43 import java.awt.Image;
       
    44 import java.awt.Toolkit;
       
    45 import java.awt.event.ActionEvent;
       
    46 import java.awt.event.ActionListener;
       
    47 import java.awt.event.WindowAdapter;
       
    48 import java.awt.event.WindowEvent;
       
    49 import java.io.File;
       
    50 import java.io.FileOutputStream;
       
    51 import java.io.IOException;
       
    52 import java.nio.file.Files;
       
    53 import java.util.ArrayList;
       
    54 import java.util.Iterator;
       
    55 import java.util.logging.Level;
       
    56 import java.util.logging.Logger;
       
    57 import javax.imageio.IIOImage;
       
    58 import javax.imageio.ImageIO;
       
    59 import javax.imageio.ImageReader;
       
    60 import javax.imageio.ImageTypeSpecifier;
       
    61 import javax.imageio.ImageWriteParam;
       
    62 import javax.imageio.ImageWriter;
       
    63 import javax.imageio.metadata.IIOMetadata;
       
    64 import javax.imageio.stream.ImageInputStream;
       
    65 import javax.imageio.stream.ImageOutputStream;
       
    66 import javax.swing.JButton;
       
    67 import javax.swing.JDialog;
       
    68 import javax.swing.JLabel;
       
    69 import javax.swing.JPanel;
       
    70 import javax.swing.SwingUtilities;
       
    71 
       
    72 public final class OpaquePNGToGIFTest extends Frame {
       
    73 
       
    74     Image img = null;
       
    75     private Dimension prefImgSize = new Dimension(100, 100);
       
    76     private Color canvasColor = new Color(0, 255, 0);
       
    77     File outputFile = null;
       
    78     ImageCanvas imageCanvas = new ImageCanvas();
       
    79     FileOutputStream fos;
       
    80     private static GridBagLayout layout;
       
    81     private static JPanel mainControlPanel;
       
    82     private static JPanel resultButtonPanel;
       
    83     private static JPanel canvasPanel;
       
    84     private static JLabel instructionText;
       
    85     private static JButton startTestButton;
       
    86     private static JButton passButton;
       
    87     private static JButton failButton;
       
    88     private static JDialog dialog;
       
    89     private static Frame instructionFrame;
       
    90     private static Frame imageFrame;
       
    91     Toolkit tk;
       
    92     ImageWriter writer = null;
       
    93     boolean testPassed, testGeneratedInterrupt, startButtonClicked;
       
    94     private static Thread mainThread;
       
    95 
       
    96     public OpaquePNGToGIFTest() throws Exception {
       
    97         SwingUtilities.invokeAndWait(() -> {
       
    98             try {
       
    99                 startTest();
       
   100             } catch (Exception ex) {
       
   101                 Logger.getLogger(OpaquePNGToGIFTest.class.getName()).
       
   102                         log(Level.SEVERE, null, ex);
       
   103             }
       
   104         });
       
   105         mainThread = Thread.currentThread();
       
   106         try {
       
   107             Thread.sleep(60000);
       
   108         } catch (InterruptedException e) {
       
   109             if (!testPassed && testGeneratedInterrupt) {
       
   110                 throw new RuntimeException("Test failed or didnt run"
       
   111                         + " properly");
       
   112             }
       
   113         }
       
   114         if (!testGeneratedInterrupt) {
       
   115             if (img != null) {
       
   116                 img.flush();
       
   117             }
       
   118             instructionFrame.dispose();
       
   119             if (startButtonClicked) {
       
   120                 imageFrame.dispose();
       
   121             }
       
   122             fos.close();
       
   123             Files.delete(outputFile.toPath());
       
   124             throw new RuntimeException("user has not executed the test");
       
   125         }
       
   126     }
       
   127 
       
   128     public void startTest() throws Exception {
       
   129         instructionFrame = new Frame();
       
   130         dialog = new JDialog(instructionFrame);
       
   131         dialog.setTitle("Instruction Dialog");
       
   132         layout = new GridBagLayout();
       
   133         mainControlPanel = new JPanel(layout);
       
   134         resultButtonPanel = new JPanel(layout);
       
   135         canvasPanel = new JPanel();
       
   136         GridBagConstraints gbc = new GridBagConstraints();
       
   137         String instructions
       
   138                 = "<html>    INSTRUCTIONS:<br><br>"
       
   139                 + "After clicking on Start Test button you will see Red<br> "
       
   140                 + " circle drawn with light blue background, if the circle<br>"
       
   141                 + " color changes from Red to Green then press button Fail,<br>"
       
   142                 + " if it stays Red then press button Pass.<br><br></html>";
       
   143         instructionText = new JLabel();
       
   144         instructionText.setText(instructions);
       
   145 
       
   146         gbc.gridx = 0;
       
   147         gbc.gridy = 0;
       
   148         gbc.fill = GridBagConstraints.HORIZONTAL;
       
   149         mainControlPanel.add(instructionText, gbc);
       
   150         startTestButton = new JButton("Start Test");
       
   151         startTestButton.setActionCommand("Start Test");
       
   152         startTestButton.addActionListener(new ActionListener() {
       
   153             @Override
       
   154             public void actionPerformed(ActionEvent e) {
       
   155                 try {
       
   156                     startButtonClicked = true;
       
   157                     imageFrame = new Frame();
       
   158 
       
   159                     Iterator it = ImageIO.getImageWritersByFormatName("GIF");
       
   160                     while (it.hasNext()) {
       
   161                         writer = (ImageWriter) it.next();
       
   162                         break;
       
   163                     }
       
   164                     // read input opaque PNG image.
       
   165                     String fileName = "opaque_input.png";
       
   166                     String sep = System.getProperty("file.separator");
       
   167                     String dir = System.getProperty("test.src", ".");
       
   168                     System.out.println(dir + "     " + sep);
       
   169                     String filePath = dir + sep + fileName;
       
   170                     File inputFile = new File(filePath);
       
   171                     ImageInputStream iis = ImageIO.
       
   172                             createImageInputStream(inputFile);
       
   173                     ImageReader reader = null;
       
   174                     Iterator readerIter = ImageIO.getImageReaders(iis);
       
   175                     while (readerIter.hasNext()) {
       
   176                         reader = (ImageReader) readerIter.next();
       
   177                         break;
       
   178                     }
       
   179 
       
   180                     reader.setInput(iis);
       
   181                     IIOMetadata imgData = reader.getImageMetadata(0);
       
   182                     BufferedImage bi = reader.read(0);
       
   183 
       
   184                     //create temporary GIF imageas output
       
   185                     File directory = new File(dir + sep);
       
   186                     outputFile = File.createTempFile("output",
       
   187                             ".gif", directory);
       
   188                     createAnimatedImage(bi, imgData,
       
   189                             writer, outputFile);
       
   190                     writer.dispose();
       
   191                     iis.close();
       
   192                     if (outputFile == null) {
       
   193                         throw new RuntimeException("Unable to create output GIF"
       
   194                                 + " file");
       
   195                     }
       
   196                     // extract GIF image using Toolkit and show it on a Panel.
       
   197                     tk = Toolkit.getDefaultToolkit();
       
   198                     img = tk.getImage(dir + sep + outputFile.getName());
       
   199                     directory.delete();
       
   200                     imageCanvas.setBackground(canvasColor);
       
   201                     imageCanvas.setImage(img);
       
   202                     imageCanvas.setPreferredSize(prefImgSize);
       
   203                     canvasPanel.doLayout();
       
   204 
       
   205                     canvasPanel.add(imageCanvas);
       
   206                     imageFrame.add("Center", canvasPanel);
       
   207                     imageFrame.setSize(200, 200);
       
   208                     imageFrame.setVisible(true);
       
   209                     imageFrame.addWindowListener(new WindowAdapter() {
       
   210                         @Override
       
   211                         public void windowClosing(WindowEvent e) {
       
   212                             try {
       
   213                                 img.flush();
       
   214                                 instructionFrame.dispose();
       
   215                                 imageFrame.dispose();
       
   216                                 fail();
       
   217                             } finally {
       
   218                                 try {
       
   219                                     fos.close();
       
   220                                     Files.delete(outputFile.toPath());
       
   221                                 } catch (IOException ex) {
       
   222                                     Logger.getLogger(OpaquePNGToGIFTest.class.
       
   223                                             getName()).log(Level.SEVERE, null,
       
   224                                                     ex);
       
   225                                 }
       
   226                             }
       
   227                         }
       
   228                     });
       
   229                 } catch (IOException ex) {
       
   230                     Logger.getLogger(OpaquePNGToGIFTest.class.getName()).
       
   231                             log(Level.SEVERE, null, ex);
       
   232                 }
       
   233             }
       
   234         });
       
   235         passButton = new JButton("Pass");
       
   236         passButton.setActionCommand("Pass");
       
   237         passButton.addActionListener(new ActionListener() {
       
   238             @Override
       
   239             public void actionPerformed(ActionEvent e) {
       
   240                 try {
       
   241                     if (img != null) {
       
   242                         img.flush();
       
   243                     }
       
   244                     instructionFrame.dispose();
       
   245                     if (!startButtonClicked) {
       
   246                         fail();
       
   247                     } else {
       
   248                         imageFrame.dispose();
       
   249                         pass();
       
   250                     }
       
   251                 } finally {
       
   252                     try {
       
   253                         fos.close();
       
   254                         Files.delete(outputFile.toPath());
       
   255                     } catch (IOException ex) {
       
   256                         Logger.getLogger(OpaquePNGToGIFTest.class.
       
   257                                 getName()).log(Level.SEVERE, null, ex);
       
   258                     }
       
   259                 }
       
   260             }
       
   261         });
       
   262         failButton = new JButton("Fail");
       
   263         failButton.setActionCommand("Fail");
       
   264         failButton.addActionListener(new ActionListener() {
       
   265             @Override
       
   266             public void actionPerformed(ActionEvent e) {
       
   267                 try {
       
   268                     if (img != null) {
       
   269                         img.flush();
       
   270                     }
       
   271                     instructionFrame.dispose();
       
   272                     if (!startButtonClicked) {
       
   273                         fail();
       
   274                     } else {
       
   275                         imageFrame.dispose();
       
   276                         fail();
       
   277                     }
       
   278                 } finally {
       
   279                     try {
       
   280                         fos.close();
       
   281                         Files.delete(outputFile.toPath());
       
   282                     } catch (IOException ex) {
       
   283                         Logger.getLogger(OpaquePNGToGIFTest.class.
       
   284                                 getName()).log(Level.SEVERE, null, ex);
       
   285                     }
       
   286                 }
       
   287             }
       
   288         });
       
   289         gbc.gridx = 1;
       
   290         gbc.gridy = 0;
       
   291         resultButtonPanel.add(startTestButton, gbc);
       
   292         gbc.gridx = 2;
       
   293         gbc.gridy = 0;
       
   294         resultButtonPanel.add(passButton, gbc);
       
   295         gbc.gridx = 3;
       
   296         gbc.gridy = 0;
       
   297         resultButtonPanel.add(failButton, gbc);
       
   298 
       
   299         gbc.gridx = 0;
       
   300         gbc.gridy = 1;
       
   301         mainControlPanel.add(resultButtonPanel, gbc);
       
   302 
       
   303         dialog.add(mainControlPanel);
       
   304         dialog.setSize(400, 200);
       
   305         dialog.setLocationRelativeTo(null);
       
   306         dialog.setVisible(true);
       
   307 
       
   308         dialog.addWindowListener(new WindowAdapter() {
       
   309             @Override
       
   310             public void windowClosing(WindowEvent e) {
       
   311                 try {
       
   312                     if (img != null) {
       
   313                         img.flush();
       
   314                     }
       
   315                     instructionFrame.dispose();
       
   316                     if (!startButtonClicked) {
       
   317                         fail();
       
   318                     } else {
       
   319                         imageFrame.dispose();
       
   320                         fail();
       
   321                     }
       
   322                 } finally {
       
   323                     try {
       
   324                         fos.close();
       
   325                         Files.delete(outputFile.toPath());
       
   326                     } catch (IOException ex) {
       
   327                         Logger.getLogger(OpaquePNGToGIFTest.class.
       
   328                                 getName()).log(Level.SEVERE, null, ex);
       
   329                     }
       
   330                 }
       
   331             }
       
   332         });
       
   333     }
       
   334 
       
   335     public synchronized void pass() {
       
   336         testPassed = true;
       
   337         testGeneratedInterrupt = true;
       
   338         mainThread.interrupt();
       
   339     }
       
   340 
       
   341     public synchronized void fail() {
       
   342         testPassed = false;
       
   343         testGeneratedInterrupt = true;
       
   344         mainThread.interrupt();
       
   345     }
       
   346 
       
   347     public void createAnimatedImage(BufferedImage bi, IIOMetadata metadata,
       
   348             ImageWriter writer, File outputFile) {
       
   349         try {
       
   350 
       
   351             fos = new FileOutputStream(outputFile);
       
   352             ImageOutputStream ios = ImageIO.createImageOutputStream(fos);
       
   353             System.out.println(ios);
       
   354             writer.setOutput(ios);
       
   355 
       
   356             ImageWriteParam param = writer.getDefaultWriteParam();
       
   357             IIOMetadata streamData = writer.getDefaultStreamMetadata(param);
       
   358 
       
   359             writer.prepareWriteSequence(streamData);
       
   360             ImageTypeSpecifier specify = new ImageTypeSpecifier(bi);
       
   361             IIOMetadata imgData = writer.convertImageMetadata(
       
   362                     (IIOMetadata) metadata, specify, param);
       
   363             GIFImageMetadata gifData = setAnimationProperties(imgData);
       
   364             IIOImage iim = new IIOImage(bi, null, gifData);
       
   365             param.setProgressiveMode(param.MODE_DISABLED);
       
   366             writer.writeToSequence(iim, param);
       
   367             writer.endWriteSequence();
       
   368             ios.close();
       
   369         } catch (Exception e) {
       
   370             e.printStackTrace();
       
   371         }
       
   372     }
       
   373 
       
   374     public GIFImageMetadata setAnimationProperties(IIOMetadata data) {
       
   375         ArrayList appIDs = new ArrayList();
       
   376         appIDs.add(new String("NETSCAPE").getBytes());
       
   377         ArrayList authCodes = new ArrayList();
       
   378         authCodes.add(new String("2.0").getBytes());
       
   379         ArrayList appData = new ArrayList();
       
   380         byte[] authData = {1, 0, 0};
       
   381         appData.add(authData);
       
   382 
       
   383         GIFImageMetadata gifData = (GIFImageMetadata) data;
       
   384         gifData.delayTime = 200;
       
   385         // If we set disposalMethod to 2 then only the issue is reproduced.
       
   386         gifData.disposalMethod = 2;
       
   387         gifData.userInputFlag = false;
       
   388 
       
   389         gifData.applicationIDs = appIDs;
       
   390         gifData.authenticationCodes = authCodes;
       
   391         gifData.applicationData = appData;
       
   392 
       
   393         return gifData;
       
   394     }
       
   395 
       
   396     public static void main(String args[]) throws Exception {
       
   397         OpaquePNGToGIFTest test = new OpaquePNGToGIFTest();
       
   398     }
       
   399 
       
   400     class ImageCanvas extends Canvas {
       
   401 
       
   402         Image im = null;
       
   403 
       
   404         public void setImage(Image img) {
       
   405             im = img;
       
   406         }
       
   407 
       
   408         public void clearImage() {
       
   409             im = null;
       
   410             repaint();
       
   411         }
       
   412 
       
   413         public void paint(Graphics g) {
       
   414             Graphics2D g2d = (Graphics2D) g;
       
   415 
       
   416             if (im != null) {
       
   417                 g2d.drawImage(im, 1, 1, getWidth(), getHeight(), this);
       
   418             }
       
   419         }
       
   420     }
       
   421 }
       
   422