1 /*
   2  * Copyright (c) 2008, 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     6541476
  27  * @summary Test verifies that ImageIO PNG plugin correcly handles the
  28  *          iTxt chunk (International textual data).
  29  *
  30  * @run     main ITXtTest
  31  */
  32 
  33 
  34 import java.awt.Color;
  35 import java.awt.Graphics2D;
  36 import java.awt.image.BufferedImage;
  37 import java.io.File;
  38 
  39 import javax.imageio.ImageIO;
  40 import javax.imageio.ImageReader;
  41 import javax.imageio.IIOImage;
  42 import javax.imageio.ImageTypeSpecifier;
  43 import javax.imageio.ImageWriter;
  44 import javax.imageio.metadata.IIOMetadata;
  45 import javax.imageio.metadata.IIOMetadataNode;
  46 import javax.imageio.stream.ImageOutputStream;
  47 import javax.imageio.stream.ImageInputStream;
  48 import java.io.IOException;
  49 
  50 import org.w3c.dom.Node;
  51 
  52 public class ITXtTest {
  53     static public void main(String args[]) throws IOException {
  54         ITXtTest t_en = new ITXtTest();
  55         t_en.description = "xml - en";
  56         t_en.keyword = "XML:com.adobe.xmp";
  57         t_en.isCompressed = false;
  58         t_en.compression = 0;
  59         t_en.language = "en";
  60         t_en.trasKeyword = "XML:com.adobe.xmp";
  61         t_en.text = "<xml>Something</xml>";
  62 
  63         doTest(t_en);
  64 
  65         // check compression case
  66         t_en.isCompressed = true;
  67         t_en.description = "xml - en - compressed";
  68 
  69         doTest(t_en);
  70 
  71         ITXtTest t_ru = new ITXtTest();
  72         t_ru.description = "xml - ru";
  73         t_ru.keyword = "XML:com.adobe.xmp";
  74         t_ru.isCompressed = false;
  75         t_ru.compression = 0;
  76         t_ru.language = "ru";
  77         t_ru.trasKeyword = "\u0410\u0410\u0410\u0410\u0410 XML";
  78         t_ru.text = "<xml>\u042A\u042F\u042F\u042F\u042F\u042F\u042F</xml>";
  79 
  80         doTest(t_ru);
  81 
  82         t_ru.isCompressed = true;
  83         t_ru.description = "xml - ru - compressed";
  84 
  85         doTest(t_ru);
  86     }
  87 
  88 
  89     String description;
  90 
  91     String keyword;
  92     boolean isCompressed;
  93     int compression;
  94     String language;
  95     String trasKeyword;
  96     String text;
  97 
  98 
  99     public IIOMetadataNode getNode() {
 100         IIOMetadataNode iTXt = new IIOMetadataNode("iTXt");
 101         IIOMetadataNode iTXtEntry = new IIOMetadataNode("iTXtEntry");
 102         iTXtEntry.setAttribute("keyword", keyword);
 103         iTXtEntry.setAttribute("compressionFlag",
 104                                isCompressed ? "true" : "false");
 105         iTXtEntry.setAttribute("compressionMethod",
 106                                Integer.toString(compression));
 107         iTXtEntry.setAttribute("languageTag", language);
 108         iTXtEntry.setAttribute("translatedKeyword",
 109                                trasKeyword);
 110         iTXtEntry.setAttribute("text", text);
 111         iTXt.appendChild(iTXtEntry);
 112         return iTXt;
 113     }
 114 
 115     public static ITXtTest getFromNode(IIOMetadataNode n) {
 116         ITXtTest t = new ITXtTest();
 117 
 118         if (!"iTXt".equals(n.getNodeName())) {
 119             throw new RuntimeException("Invalid node");
 120         }
 121         IIOMetadataNode e = (IIOMetadataNode)n.getFirstChild();
 122         if (!"iTXtEntry".equals(e.getNodeName())) {
 123             throw new RuntimeException("Invalid entry node");
 124         }
 125         t.keyword = e.getAttribute("keyword");
 126         t.isCompressed =
 127             Boolean.valueOf(e.getAttribute("compressionFlag")).booleanValue();
 128         t.compression =
 129             Integer.valueOf(e.getAttribute("compressionMethod")).intValue();
 130         t.language = e.getAttribute("languageTag");
 131         t.trasKeyword = e.getAttribute("translatedKeyword");
 132         t.text = e.getAttribute("text");
 133 
 134         return t;
 135     }
 136 
 137     @Override
 138     public boolean equals(Object o) {
 139         if (! (o instanceof ITXtTest)) {
 140             return false;
 141         }
 142         ITXtTest t = (ITXtTest)o;
 143         if (!keyword.equals(t.keyword)) { return false; }
 144         if (isCompressed != t.isCompressed) { return false; }
 145         if (compression != t.compression) { return false; }
 146         if (!language.equals(t.language)) { return false; }
 147         if (!trasKeyword.equals(t.trasKeyword)) { return false; }
 148         if (!text.equals(t.text)) { return false; }
 149 
 150         return true;
 151     }
 152 
 153 
 154 
 155     private static void doTest(ITXtTest src) throws IOException {
 156 
 157         System.out.println("Test: " + src.description);
 158 
 159         File file = new File("test.png");
 160 
 161         writeTo(file, src);
 162         ITXtTest dst = readFrom(file);
 163 
 164         if (dst == null || !dst.equals(src)) {
 165             file.delete();
 166             throw new RuntimeException("Test failed.");
 167         } else {
 168             file.delete();
 169             System.out.println("Test passed.");
 170         }
 171     }
 172 
 173     private static void writeTo(File f, ITXtTest t) throws IOException {
 174         BufferedImage src = createBufferedImage();
 175         ImageOutputStream imageOutputStream = null;
 176         try {
 177             imageOutputStream =
 178                 ImageIO.createImageOutputStream(f);
 179 
 180             ImageTypeSpecifier imageTypeSpecifier =
 181                 new ImageTypeSpecifier(src);
 182             ImageWriter imageWriter =
 183                 ImageIO.getImageWritersByFormatName("PNG").next();
 184 
 185             imageWriter.setOutput(imageOutputStream);
 186 
 187             IIOMetadata m =
 188                 imageWriter.getDefaultImageMetadata(imageTypeSpecifier, null);
 189 
 190             String format = m.getNativeMetadataFormatName();
 191             Node root = m.getAsTree(format);
 192 
 193             IIOMetadataNode iTXt = t.getNode();
 194             root.appendChild(iTXt);
 195             m.setFromTree(format, root);
 196 
 197             imageWriter.write(new IIOImage(src, null, m));
 198             imageOutputStream.close();
 199             System.out.println("Writing done.");
 200         } catch (Throwable e) {
 201             if (imageOutputStream != null) {
 202                 imageOutputStream.close();
 203             }
 204             f.delete();
 205             throw new RuntimeException("Writing test failed.", e);
 206         }
 207     }
 208 
 209     private static ITXtTest readFrom(File f) throws IOException {
 210         ImageInputStream iis = null;
 211         try {
 212             iis = ImageIO.createImageInputStream(f);
 213             ImageReader r = ImageIO.getImageReaders(iis).next();
 214             r.setInput(iis);
 215 
 216             IIOImage dst = r.readAll(0, null);
 217 
 218             // look for iTXt node
 219             IIOMetadata m = dst.getMetadata();
 220             Node root = m.getAsTree(m.getNativeMetadataFormatName());
 221             Node n = root.getFirstChild();
 222             while (n != null && !"iTXt".equals(n.getNodeName())) {
 223                 n = n.getNextSibling();
 224             }
 225             if (n == null) {
 226                 throw new RuntimeException("No iTXt node!");
 227             }
 228             ITXtTest t = ITXtTest.getFromNode((IIOMetadataNode)n);
 229             iis.close();
 230             return t;
 231         } catch (Throwable e) {
 232             if (iis != null) {
 233                 iis.close();
 234             }
 235             f.delete();
 236             throw new RuntimeException("Reading test failed.", e);
 237         }
 238     }
 239 
 240     private static BufferedImage createBufferedImage() {
 241         BufferedImage image = new BufferedImage(128, 128,
 242                       BufferedImage.TYPE_4BYTE_ABGR_PRE);
 243         Graphics2D graph = image.createGraphics();
 244         graph.setPaintMode();
 245         graph.setColor(Color.orange);
 246         graph.fillRect(32, 32, 64, 64);
 247         graph.dispose();
 248         return image;
 249     }
 250 }