Path: blob/master/test/jdk/javax/imageio/plugins/png/ShortHistogramTest.java
41155 views
/*1* Copyright (c) 2007, 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 619811126* @summary Test verifies that PNG image reader correctly handles27* hIST chunk if length of image palette in not power of two.28*29* @run main ShortHistogramTest 1530*/3132import java.awt.Color;33import java.awt.Graphics2D;34import java.awt.image.BufferedImage;35import java.awt.image.DataBuffer;36import java.awt.image.IndexColorModel;37import java.awt.image.Raster;38import java.io.File;39import java.io.IOException;40import java.util.Arrays;41import java.util.Random;42import javax.imageio.IIOImage;43import javax.imageio.ImageIO;44import javax.imageio.ImageTypeSpecifier;45import javax.imageio.ImageWriteParam;46import javax.imageio.ImageWriter;47import javax.imageio.metadata.IIOInvalidTreeException;48import javax.imageio.metadata.IIOMetadata;49import javax.imageio.metadata.IIOMetadataNode;50import javax.imageio.stream.ImageOutputStream;51import org.w3c.dom.NamedNodeMap;52import org.w3c.dom.Node;5354public class ShortHistogramTest {5556public static void main(String[] args) throws IOException {57int numColors = 15;58if (args.length > 0) {59try {60numColors = Integer.parseInt(args[0]);61} catch (NumberFormatException e) {62System.out.println("Invalid number of colors: " + args[0]);63}64}65System.out.println("Test number of colors: " + numColors);6667ShortHistogramTest t = new ShortHistogramTest(numColors);68t.doTest();69}7071int numColors;7273public ShortHistogramTest(int numColors) {74this.numColors = numColors;75}7677public void doTest() throws IOException {78BufferedImage bi = createTestImage(numColors);7980File f = writeImageWithHist(bi);81System.out.println("Test file is " + f.getCanonicalPath());8283try {84ImageIO.read(f);85} catch (IOException e) {86throw new RuntimeException("Test FAILED!", e);87}88System.out.println("Test PASSED!");89}9091protected File writeImageWithHist(BufferedImage bi) throws IOException {92File f = File.createTempFile("hist_", ".png", new File("."));9394ImageWriter writer = ImageIO.getImageWritersByFormatName("PNG").next();9596ImageOutputStream ios = ImageIO.createImageOutputStream(f);97writer.setOutput(ios);9899ImageWriteParam param = writer.getDefaultWriteParam();100ImageTypeSpecifier type = new ImageTypeSpecifier(bi);101102IIOMetadata imgMetadata = writer.getDefaultImageMetadata(type, param);103104/* add hIST node to image metadata */105imgMetadata = upgradeMetadata(imgMetadata, bi);106107IIOImage iio_img = new IIOImage(bi,108null, // no thumbnails109imgMetadata);110111writer.write(iio_img);112ios.flush();113ios.close();114return f;115}116117private IIOMetadata upgradeMetadata(IIOMetadata src, BufferedImage bi) {118String format = src.getNativeMetadataFormatName();119System.out.println("Native format: " + format);120Node root = src.getAsTree(format);121122// add hIST node123Node n = lookupChildNode(root, "hIST");124if (n == null) {125System.out.println("Appending new hIST node...");126Node hIST = gethISTNode(bi);127root.appendChild(hIST);128}129130System.out.println("Upgraded metadata tree:");131dump(root, "");132133System.out.println("Merging metadata...");134try {135src.mergeTree(format, root);136} catch (IIOInvalidTreeException e) {137throw new RuntimeException("Test FAILED!", e);138}139return src;140}141142private IIOMetadataNode gethISTNode(BufferedImage bi) {143IndexColorModel icm = (IndexColorModel)bi.getColorModel();144int mapSize = icm.getMapSize();145146int[] hist = new int[mapSize];147Arrays.fill(hist, 0);148149Raster r = bi.getData();150for (int y = 0; y < bi.getHeight(); y++) {151for (int x = 0; x < bi.getWidth(); x++) {152int s = r.getSample(x, y, 0);153hist[s] ++;154}155}156157IIOMetadataNode hIST = new IIOMetadataNode("hIST");158for (int i = 0; i < hist.length; i++) {159IIOMetadataNode n = new IIOMetadataNode("hISTEntry");160n.setAttribute("index", "" + i);161n.setAttribute("value", "" + hist[i]);162hIST.appendChild(n);163}164165return hIST;166}167168private static Node lookupChildNode(Node root, String name) {169Node n = root.getFirstChild();170while (n != null && !name.equals(n.getNodeName())) {171n = n.getNextSibling();172}173return n;174}175176private static void dump(Node node, String ident) {177if (node == null) {178return;179}180181System.out.printf("%s%s\n", ident, node.getNodeName());182183// dump node attributes...184NamedNodeMap attribs = node.getAttributes();185if (attribs != null) {186for (int i = 0; i < attribs.getLength(); i++) {187Node a = attribs.item(i);188System.out.printf("%s %s: %s\n", ident,189a.getNodeName(), a.getNodeValue());190}191}192// dump node children...193dump(node.getFirstChild(), ident + " ");194195dump(node.getNextSibling(), ident);196}197198protected BufferedImage createTestImage(int numColors) {199200IndexColorModel icm = createTestICM(numColors);201int w = numColors * 10;202int h = 20;203204BufferedImage img = new BufferedImage(w, h,205BufferedImage.TYPE_BYTE_INDEXED, icm);206207Graphics2D g = img.createGraphics();208for (int i = 0; i < numColors; i++) {209int rgb = icm.getRGB(i);210//System.out.printf("pixel %d, rgb %x\n", i, rgb);211g.setColor(new Color(rgb));212g.fillRect(i * 10, 0, w - i * 10, h);213}214g.dispose();215216return img;217}218219protected IndexColorModel createTestICM(int numColors) {220int[] palette = createTestPalette(numColors);221222int numBits = getNumBits(numColors);223224IndexColorModel icm = new IndexColorModel(numBits, numColors,225palette, 0, false, -1,226DataBuffer.TYPE_BYTE);227return icm;228}229230protected static int getNumBits(int numColors) {231if (numColors < 0 || 256 < numColors) {232throw new RuntimeException("Unsupported number of colors: " +233numColors);234}235236int numBits = 1;237int limit = 1 << numBits;238while (numColors > limit) {239numBits++;240limit = 1 << numBits;241}242return numBits;243}244245private static Random rnd = new Random();246247protected static int[] createTestPalette(int numColors) {248int[] palette = new int[numColors];249for (int i = 0; i < numColors; i++) {250int r = rnd.nextInt(256);251int g = rnd.nextInt(256);252int b = rnd.nextInt(256);253254palette[i] = 0xff000000 | (r << 16) | (g << 8) | b;255}256return palette;257}258}259260261