Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I save a PNG with a tEXt or iTXt chunk from Java?

I am currently using javax.imageio.ImageIO to write a PNG file. I would like to include a tEXt chunk (and indeed any of the chunks listed here), but can see no means of doing so.

By the looks of com.sun.imageio.plugins.png.PNGMetadata it should be possible.

I should be most grateful for any clues or answers.

M.

like image 397
Martin Cowie Avatar asked Apr 06 '09 15:04

Martin Cowie


People also ask

How do I convert png to TXT?

Select PNG files you want to convert, from your computer or drag and drop it on the page. Press the "Convert" button in order to convert PNG to TXT. When the conversion is completed, click "Download" on the desired converted TXT file. Portable Network Graphics (PNG) is a raster-graphics file format that supports lossless data compression.

How do I save an image as png?

The PNG (portable network graphics) file format is a popular image format used in graphic design. If you have an image file in JPEG or GIF format, for example, you can use the most basic graphics editor to save that image as PNG format. To learn how, you can start by seeing part 1. Launch your favorite search engine.

How to make a PNG file easier to find?

If the PNG you're downloading is of a red tree in fall, don't name it "Winter tree". This will only confuse you more. Sometimes, less is more. You may just want to name your PNG file "PNG1", if that helps you. Add image tags to the file. This adds an extra layer of descriptiveness to easily find your PNG.

Why would I want to save a file in JPEG format?

Sometimes when managing word processing or text documents you might want to save the file in a compressed JPEG format or other similar picture format.


2 Answers

I realise this question is long since answered, but if you want to do it without dipping into the "com.sun" hierarchy, here's an quick and very ugly example as I couldn't find this documented anywhere else.

BufferedImage img = new BufferedImage(300, 300, BufferedImage.TYPE_INT_ARGB);

// Create a DOM Document describing the metadata;
// I've gone the quick and dirty route. The description for PNG is at
// [http://download.oracle.com/javase/1.4.2/docs/api/javax/imageio/metadata/doc-files/png_metadata.html][1]

Calendar c = Calendar.getInstance();
String xml = "<?xml version='1.0'?><javax_imageio_png_1.0><tIME year='"+c.get(c.YEAR)+"' month='"+(c.get(c.MONTH)+1)+"' day='"+c.get(c.DAY_OF_MONTH)+"' hour='"+c.get(c.HOUR_OF_DAY)+"' minute='"+c.get(c.MINUTE)+"' second='"+c.get(c.SECOND)+"'/><pHYs pixelsPerUnitXAxis='"+11811+"' pixelsPerUnitYAxis='"+11811+"' unitSpecifier='meter'/></javax_imageio_png_1.0>";
DOMResult domresult = new DOMResult();
TransformerFactory.newInstance().newTransformer().transform(new StreamSource(new StringReader(xml)), domresult);
Document document = dom.getResult();

// Apply the metadata to the image
ImageWriter writer = (ImageWriter)ImageIO.getImageWritersBySuffix("png").next();
IIOMetadata meta = writer.getDefaultImageMetadata(new ImageTypeSpecifier(img), null);
meta.setFromTree(meta.getMetadataFormatNames()[0], document.getFirstChild());
FileOutputStream out = new FileOutputStream("out.png");
writer.setOutput(ImageIO.createImageOutputStream(out));
writer.write(new IIOImage(img, null, meta));
out.close();
like image 197
Mike B Avatar answered Oct 20 '22 06:10

Mike B


We do this in the JGraphX project. Download the source code and have a look in the com.mxgraph.util.png package, there you'll find three classes for encoding that we copied from the Apache Batik sources. An example of usage is in com.mxgraph.examples.swing.editor.EditorActions in the saveXmlPng method. Slightly edited the code looks like:

mxPngEncodeParam param = mxPngEncodeParam
  .getDefaultEncodeParam(image);
param.setCompressedText(new String[] { "mxGraphModel", xml });

// Saves as a PNG file
FileOutputStream outputStream = new FileOutputStream(new File(
  filename));
try
{
 mxPngImageEncoder encoder = new mxPngImageEncoder(outputStream,
   param);

 if (image != null)
 {
  encoder.encode(image);
 }
}
finally
{
 outputStream.close();
}

Where image is the BufferedImage that will form the .PNG and xml is the string we wish to place in the iTxt section. "mxGraphModel" is the key for that xml string (the section comprises some number of key/value pairs), obviously you replace that with your key.

Also under com.mxgraph.util.png we've written a really simple class that extracts the iTxt without processing the whole image. You could apply the same idea for the tEXt chunk using mxPngEncodeParam.setText instead of setCompressedText(), but the compressed text section does allow for considerable larger text sections.

like image 21
Thomas the Tank Engine Avatar answered Oct 20 '22 06:10

Thomas the Tank Engine