All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sourceforge.plantuml.png.PngIOMetadata Maven / Gradle / Ivy

There is a newer version: 1.2024.8
Show newest version
// THIS FILE HAS BEEN GENERATED BY A PREPROCESSOR.
/* +=======================================================================
 * |
 * |      PlantUML : a free UML diagram generator
 * |
 * +=======================================================================
 *
 * (C) Copyright 2009-2024, Arnaud Roques
 *
 * Project Info:  https://plantuml.com
 *
 * If you like this project or if you find it useful, you can support us at:
 *
 * https://plantuml.com/patreon (only 1$ per month!)
 * https://plantuml.com/liberapay (only 1€ per month!)
 * https://plantuml.com/paypal
 *
 *
 * PlantUML is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * PlantUML 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 Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library.  If not, see .
 *
 * PlantUML can occasionally display sponsored or advertising messages. Those
 * messages are usually generated on welcome or error images and never on
 * functional diagrams.
 * See https://plantuml.com/professional if you want to remove them
 *
 * Images (whatever their format : PNG, SVG, EPS...) generated by running PlantUML
 * are owned by the author of their corresponding sources code (that is, their
 * textual description in PlantUML language). Those images are not covered by
 * this LGPL license.
 *
 * The generated images can then be used without any reference to the LGPL license.
 * It is not even necessary to stipulate that they have been generated with PlantUML,
 * although this will be appreciated by the PlantUML team.
 *
 * There is an exception : if the textual description in PlantUML language is also covered
 * by any license, then the generated images are logically covered
 * by the very same license.
 *
 * This is the IGY distribution (Install GraphViz by Yourself).
 * You have to install GraphViz and to setup the GRAPHVIZ_DOT environment variable
 * (see https://plantuml.com/graphviz-dot )
 *
 * Icons provided by OpenIconic :  https://useiconic.com/open
 * Archimate sprites provided by Archi :  http://www.archimatetool.com
 * Stdlib AWS provided by https://github.com/milo-minderbinder/AWS-PlantUML
 * Stdlib Icons provided https://github.com/tupadr3/plantuml-icon-font-sprites
 * ASCIIMathML (c) Peter Jipsen http://www.chapman.edu/~jipsen
 * ASCIIMathML (c) David Lippman http://www.pierce.ctc.edu/dlippman
 * CafeUndZopfli ported by Eugene Klyuchnikov https://github.com/eustas/CafeUndZopfli
 * Brotli (c) by the Brotli Authors https://github.com/google/brotli
 * Themes (c) by Brett Schwarz https://github.com/bschwarz/puml-themes
 * Twemoji (c) by Twitter at https://twemoji.twitter.com/
 *
 */
package net.sourceforge.plantuml.png;

import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;

import javax.imageio.IIOImage;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.stream.ImageOutputStream;

import net.sourceforge.plantuml.security.SImageIO;
import net.sourceforge.plantuml.utils.Log;

public class PngIOMetadata {
	// ::remove file when __CORE__

	private static final String copyleft = "Generated by https://plantuml.com";

	public static void writeWithMetadata(RenderedImage image, OutputStream os, String metadata, int dpi,
			String debugData) throws IOException {

//		Log.info("Cannot create com.sun.imageio.plugins.png.PNGMetadata");
//		PngIO.forceImageIO = true;
//		ImageIO.write(image, "png", os);

		writeInternal(image, os, metadata, dpi, debugData);
	}

	private static void writeInternal(RenderedImage image, OutputStream os, String metadata, int dpi, String debugData)
			throws IOException {

		final ImageWriter writer = javax.imageio.ImageIO.getImageWritersByFormatName("png").next();
		final ImageWriteParam writeParam = writer.getDefaultWriteParam();
		final ImageTypeSpecifier typeSpecifier = ImageTypeSpecifier
				.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB);

		final IIOMetadata meta = writer.getDefaultImageMetadata(typeSpecifier, writeParam);

		if (dpi != 96) {
			addDpi(meta, dpi);
		}

		if (debugData != null) {
			addText(meta, "debug", debugData);
		}
		addText(meta, "copyleft", copyleft);
		addiText(meta, "plantuml", metadata);

		Log.debug("PngIOMetadata pngMetadata=" + meta);

		// Render the PNG to file
		final IIOImage iioImage = new IIOImage(image, null, meta);
		Log.debug("PngIOMetadata iioImage=" + iioImage);
		// Attach the metadata
		final ImageWriter imagewriter = getImageWriter();
		Log.debug("PngIOMetadata imagewriter=" + imagewriter);

		// See
		// http://plantuml.sourceforge.net/qa/?qa=4367/sometimes-missing-response-headers-for-broken-png-images
		// Code provided by Michael Griffel
		synchronized (imagewriter) {
			final ImageOutputStream imageOutputStream = SImageIO.createImageOutputStream(os);
			imagewriter.setOutput(imageOutputStream);
			try {
				imagewriter.write(null /* default */, iioImage, null /* use default ImageWriteParam */);
			} finally {
				// os.flush();
				// Log.debug("PngIOMetadata finally 1");
				imageOutputStream.flush();
				// Log.debug("PngIOMetadata finally 2");
				imageOutputStream.close();
				// Log.debug("PngIOMetadata finally 3");
				imagewriter.reset();
				// Log.debug("PngIOMetadata finally 4");
				imagewriter.dispose();
				// Log.debug("PngIOMetadata finally 5");
			}
		}
	}

	private static void addDpi(IIOMetadata meta, double dpi) throws IIOInvalidTreeException {
		final IIOMetadataNode dimension = new IIOMetadataNode("Dimension");

		final IIOMetadataNode horizontalPixelSize = new IIOMetadataNode("HorizontalPixelSize");
		final double value = dpi / 0.0254 / 1000;
		horizontalPixelSize.setAttribute("value", Double.toString(value));
		dimension.appendChild(horizontalPixelSize);

		final IIOMetadataNode verticalPixelSize = new IIOMetadataNode("VerticalPixelSize");
		verticalPixelSize.setAttribute("value", Double.toString(value));
		dimension.appendChild(verticalPixelSize);

		final IIOMetadataNode root = new IIOMetadataNode("javax_imageio_1.0");
		root.appendChild(dimension);

		meta.mergeTree("javax_imageio_1.0", root);

	}

	private static void addiText(IIOMetadata meta, String key, String value) throws IIOInvalidTreeException {
		final IIOMetadataNode text = new IIOMetadataNode("iTXt");
		final IIOMetadataNode entry = new IIOMetadataNode("iTXtEntry");
		entry.setAttribute("keyword", key);
		entry.setAttribute("compressionFlag", "true");
		entry.setAttribute("compressionMethod", "0");
		entry.setAttribute("languageTag", "");
		entry.setAttribute("translatedKeyword", "");
		entry.setAttribute("text", value);

		text.appendChild(entry);
		final IIOMetadataNode root = new IIOMetadataNode("javax_imageio_png_1.0");
		root.appendChild(text);

		meta.mergeTree("javax_imageio_png_1.0", root);

	}

	private static void addText(IIOMetadata meta, String key, String value) throws IIOInvalidTreeException {
		final IIOMetadataNode text = new IIOMetadataNode("tEXt");
		final IIOMetadataNode entry = new IIOMetadataNode("tEXtEntry");
		entry.setAttribute("keyword", key);
		entry.setAttribute("value", value);

		text.appendChild(entry);
		final IIOMetadataNode root = new IIOMetadataNode("javax_imageio_png_1.0");
		root.appendChild(text);

		meta.mergeTree("javax_imageio_png_1.0", root);
	}

	private static ImageWriter getImageWriter() {
		final Iterator iterator = SImageIO.getImageWritersBySuffix("png");
		for (final Iterator it = SImageIO.getImageWritersBySuffix("png"); it.hasNext();) {
			final ImageWriter imagewriter = iterator.next();
			Log.debug("PngIOMetadata countImageWriter = " + it.next());
			if (imagewriter.getClass().getName().equals("com.sun.imageio.plugins.png.PNGImageWriter")) {
				Log.debug("PngIOMetadata Found sun PNGImageWriter");
				return imagewriter;
			}

		}
		Log.debug("Using first one");
		return SImageIO.getImageWritersBySuffix("png").next();
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy