Path: blob/master/test/jdk/javax/imageio/plugins/png/PngCreationTimeTest.java
41155 views
/*1* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 8164971 818711326* @summary The test decodes a png file and checks if the metadata contains27* image creation time. In addition, the test also merges the custom28* metadata tree (both standard and native) and succeeds when the29* metadata contains expected image creation time.30* @run main PngCreationTimeTest31*/32import java.io.IOException;33import java.io.File;34import java.nio.file.Files;35import java.util.Iterator;36import java.awt.Graphics2D;37import java.awt.Color;38import java.awt.image.BufferedImage;39import javax.imageio.ImageIO;40import javax.imageio.IIOImage;41import javax.imageio.ImageTypeSpecifier;42import javax.imageio.stream.ImageInputStream;43import javax.imageio.stream.ImageOutputStream;44import javax.imageio.ImageReadParam;45import javax.imageio.ImageReader;46import javax.imageio.ImageWriter;47import javax.imageio.metadata.IIOMetadata;48import javax.imageio.metadata.IIOMetadataNode;49import org.w3c.dom.Node;50import org.w3c.dom.NamedNodeMap;5152public class PngCreationTimeTest {53// Members54private static IIOMetadata pngMetadata = null;5556public static void initializeTest() throws IOException {57Iterator<ImageReader> iterR = null;58ImageReader pngImageReader = null;59BufferedImage decImage = null;60ImageInputStream imageStream = null;61String fileName = "duke.png";62String separator = System.getProperty("file.separator");63String dirPath = System.getProperty("test.src", ".");64String filePath = dirPath + separator + fileName;65File file = null;6667try {68// Open the required file and check if file exists.69file = new File(filePath);70if (file != null && !file.exists()) {71reportExceptionAndFail("Test Failed. Required image file was"72+ " not found.");73}7475// Get PNG image reader76iterR = ImageIO.getImageReadersBySuffix("PNG");77if (iterR.hasNext()) {78pngImageReader = iterR.next();79ImageReadParam param = pngImageReader.getDefaultReadParam();80imageStream = ImageIO.createImageInputStream(file);81if (imageStream != null) {82// Last argument informs reader not to ignore metadata83pngImageReader.setInput(imageStream,84false,85false);86decImage = pngImageReader.read(0, param);87pngMetadata = pngImageReader.getImageMetadata(0);88if (pngMetadata != null) {89// Check if the metadata contains creation time90testImageMetadata(pngMetadata);91} else {92reportExceptionAndFail("Test Failed. Reader could not"93+ " generate image metadata.");94}95} else {96reportExceptionAndFail("Test Failed. Could not initialize"97+ " image input stream.");98}99} else {100reportExceptionAndFail("Test Failed. Required image reader"101+ " was not found.");102}103} finally {104// Release ther resources105if (imageStream != null) {106imageStream.close();107}108if (pngImageReader != null) {109pngImageReader.dispose();110}111}112}113114public static void testImageMetadata(IIOMetadata metadata) {115/*116* The source file contains Creation Time in its text chunk. Upon117* successful decoding, the Standard/Document/ImageCreationTime118* should exist in the metadata.119*/120if (metadata != null) {121Node keyNode = findNode(metadata.getAsTree("javax_imageio_1.0"),122"ImageCreationTime");123if (keyNode == null) {124reportExceptionAndFail("Test Failed: Could not find image"125+ " creation time in the metadata.");126}127}128}129130public static void testSaveCreationTime() throws IOException {131File file = null;132Iterator<ImageWriter> iterW = null;133Iterator<ImageReader> iterR = null;134ImageWriter pngImageWriter = null;135ImageReader pngImageReader = null;136ImageInputStream inputStream = null;137ImageOutputStream outputStream = null;138try {139// Create a simple image and fill with a color140int imageSize = 200;141BufferedImage buffImage = new BufferedImage(imageSize, imageSize,142BufferedImage.TYPE_INT_ARGB);143Graphics2D g2d = buffImage.createGraphics();144g2d.setColor(Color.red);145g2d.fillRect(0, 0, imageSize, imageSize);146147// Create a temporary file for the output png image148String fileName = "RoundTripTest";149file = File.createTempFile(fileName, ".png");150if (file == null) {151reportExceptionAndFail("Test Failed. Could not create a"152+ " temporary file for round trip test.");153}154155// Create a PNG writer and write test image with metadata156iterW = ImageIO.getImageWritersBySuffix("PNG");157if (iterW.hasNext()) {158pngImageWriter = iterW.next();159outputStream = ImageIO.createImageOutputStream(file);160if (outputStream != null) {161pngImageWriter.setOutput(outputStream);162163// Get the default metadata & add image creation time to it.164ImageTypeSpecifier imgType =165ImageTypeSpecifier.createFromRenderedImage(buffImage);166IIOMetadata metadata =167pngImageWriter.getDefaultImageMetadata(imgType, null);168IIOMetadataNode root = createStandardMetadataNodeTree();169metadata.mergeTree("javax_imageio_1.0", root);170171// Write a png image using buffImage & metadata172IIOImage iioImage = new IIOImage(buffImage, null, metadata);173pngImageWriter.write(iioImage);174} else {175reportExceptionAndFail("Test Failed. Could not initialize"176+ " image output stream for round trip test.");177}178} else {179reportExceptionAndFail("Test Failed. Could not find required"180+ " image writer for the round trip test.");181}182183// Create a PNG reader and check if metadata was written184iterR = ImageIO.getImageReadersBySuffix("PNG");185if (iterR.hasNext()) {186pngImageReader = iterR.next();187inputStream = ImageIO.createImageInputStream(file);188if (inputStream != null) {189// Read the image and get the metadata190pngImageReader.setInput(inputStream, false, false);191pngImageReader.read(0);192IIOMetadata imgMetadata =193pngImageReader.getImageMetadata(0);194195// Test if the metadata contains creation time.196testImageMetadata(imgMetadata);197} else {198reportExceptionAndFail("Test Failed. Could not initialize"199+ " image input stream for round trip test.");200}201} else {202reportExceptionAndFail("Test Failed. Cound not find the"203+ " required image reader.");204}205} finally {206// Release the resources held207if (inputStream != null) {208inputStream.close();209}210if (outputStream != null) {211outputStream.close();212}213if (pngImageWriter != null) {214pngImageWriter.dispose();215}216if (pngImageReader != null) {217pngImageReader.dispose();218}219// Delete the temp file as well220if (file != null) {221Files.delete(file.toPath());222}223}224}225226public static void reportExceptionAndFail(String message) {227// A common method to report exception.228throw new RuntimeException(message);229}230231public static void testMergeNativeTree() {232// Merge a custom native metadata tree and inspect creation time233if (pngMetadata != null) {234try {235IIOMetadataNode root = createNativeMetadataNodeTree();236237/*238* Merge the native metadata tree created. The data should239* reflect in Standard/Document/ImageCreationTime Node240*/241pngMetadata.mergeTree("javax_imageio_png_1.0", root);242Node keyNode = findNode(pngMetadata.getAsTree("javax_imageio_1.0"),243"ImageCreationTime");244if (keyNode != null) {245// Query the attributes of the node and check for the value246NamedNodeMap attrMap = keyNode.getAttributes();247String attrValue = attrMap.getNamedItem("year")248.getNodeValue();249int decYear = Integer.parseInt(attrValue);250if (decYear != 2014) {251// Throw exception. Incorrect year value observed252reportExceptionAndFail("Test Failed: Incorrect"253+ " creation time value observed.");254}255} else {256// Throw exception.257reportExceptionAndFail("Test Failed: Image creation"258+ " time doesn't exist in metadata.");259}260} catch (IOException ex) {261// Throw exception.262reportExceptionAndFail("Test Failed: While executing"263+ " mergeTree on metadata.");264}265}266}267268public static void testMergeStandardTree() {269// Merge a standard metadata tree and inspect creation time270if (pngMetadata != null) {271try {272IIOMetadataNode root = createStandardMetadataNodeTree();273274/*275* Merge the standard metadata tree created. The data should276* correctly reflect in the native tree277*/278pngMetadata.mergeTree("javax_imageio_1.0", root);279Node keyNode = findNode(pngMetadata.getAsTree("javax_imageio_png_1.0"),280"tEXtEntry");281// Last text entry would contain the merged information282while (keyNode != null && keyNode.getNextSibling() != null) {283keyNode = keyNode.getNextSibling();284}285286if (keyNode != null) {287// Query the attributes of the node and check for the value288NamedNodeMap attrMap = keyNode.getAttributes();289String attrValue = attrMap.getNamedItem("value")290.getNodeValue();291if (!attrValue.contains("2016")) {292// Throw exception. Incorrect year value observed293throw new RuntimeException("Test Failed: Incorrect"294+ " creation time value observed.");295}296} else {297// Throw exception.298reportExceptionAndFail("Test Failed: Image creation"299+ " time doesn't exist in metadata.");300}301} catch (IOException ex) {302// Throw exception.303reportExceptionAndFail("Test Failed: While executing"304+ " mergeTree on metadata.");305}306}307}308309public static IIOMetadataNode createNativeMetadataNodeTree() {310// Create a text node to hold tEXtEntries311IIOMetadataNode tEXtNode = new IIOMetadataNode("tEXt");312313// Create tEXt entry to hold random date time314IIOMetadataNode randomTimeEntry = new IIOMetadataNode("tEXtEntry");315randomTimeEntry.setAttribute("keyword", "Creation Time");316randomTimeEntry.setAttribute("value", "21 Dec 2015,Monday");317tEXtNode.appendChild(randomTimeEntry);318319// Create a tEXt entry to hold time in RFC1123 format320IIOMetadataNode rfcTextEntry = new IIOMetadataNode("tEXtEntry");321rfcTextEntry.setAttribute("keyword", "Creation Time");322rfcTextEntry.setAttribute("value", "Mon, 21 Dec 2015 09:04:30 +0530");323tEXtNode.appendChild(rfcTextEntry);324325// Create a tEXt entry to hold time in ISO format326IIOMetadataNode isoTextEntry = new IIOMetadataNode("tEXtEntry");327isoTextEntry.setAttribute("keyword", "Creation Time");328isoTextEntry.setAttribute("value", "2014-12-21T09:04:30+05:30");329tEXtNode.appendChild(isoTextEntry);330331// Create a root node append the text node332IIOMetadataNode root = new IIOMetadataNode("javax_imageio_png_1.0");333root.appendChild(tEXtNode);334335return root;336}337338public static IIOMetadataNode createStandardMetadataNodeTree() {339/*340* Create standard metadata tree with creation time in341* Standard(Root)/Document/ImageCreationTime node342*/343IIOMetadataNode createTimeNode = new IIOMetadataNode("ImageCreationTime");344createTimeNode.setAttribute("year", "2016");345createTimeNode.setAttribute("month", "12");346createTimeNode.setAttribute("day", "21");347createTimeNode.setAttribute("hour", "18");348createTimeNode.setAttribute("minute", "30");349createTimeNode.setAttribute("second", "00");350351// Create the Document node352IIOMetadataNode documentNode = new IIOMetadataNode("Document");353documentNode.appendChild(createTimeNode);354355// Create a root node append the Document node356IIOMetadataNode root = new IIOMetadataNode("javax_imageio_1.0");357root.appendChild(documentNode);358359return root;360}361362public static Node findNode(Node root, String nodeName) {363// Return value364Node retVal = null;365366if (root != null ) {367// Check if the name of root node matches the key368String name = root.getNodeName();369if (name.equalsIgnoreCase(nodeName)) {370return root;371}372373// Process all children374Node node = root.getFirstChild();375while (node != null) {376retVal = findNode(node, nodeName);377if (retVal != null ) {378// We found the node. Stop the search379break;380}381node = node.getNextSibling();382}383}384385return retVal;386}387388public static void main(String[] args) throws IOException {389/*390* Initialize the test by decoding a PNG image that has creation391* time in one of its text chunks and check if the metadata returned392* contains image creation time.393*/394initializeTest();395396/*397* Test the round trip usecase. Write a PNG file with "Creation Time"398* in text chunk and decode the same to check if the creation time399* was indeed written to the PNG file.400*/401testSaveCreationTime();402403/*404* Modify the metadata by merging a standard metadata tree and inspect405* the value in the native tree406*/407testMergeNativeTree();408409/*410* Modify the metadata by merging a native metadata tree and inspect411* the value in the standard tree.412*/413testMergeStandardTree();414}415}416417418