如何从Java保存带有tEXt或iTXt块的PNG?

问题描述 投票:11回答:6

我目前正在使用javax.imageio.ImageIO编写PNG文件。我想包括一个tEXt块(以及实际上任何块listed here),但看不到这样做的任何方法。

通过com.sun.imageio.plugins.png.PNGMetadata的外观,应该可以。

我应该对任何线索或答案深表谢意。

java text png javax.imageio
6个回答
10
投票

经过一些反编译后,我遇到的解决方案如下...

RenderedImage image = getMyImage();         
Iterator<ImageWriter> iterator = ImageIO.getImageWritersBySuffix( "png" );

if(!iterator.hasNext()) throw new Error( "No image writer for PNG" );

ImageWriter imagewriter = iterator.next();
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
imagewriter.setOutput( ImageIO.createImageOutputStream( bytes ) ); 

// Create & populate metadata
PNGMetadata metadata = new PNGMetadata();
// see http://www.w3.org/TR/PNG-Chunks.html#C.tEXt for standardized keywords
metadata.tEXt_keyword.add( "Title" );
metadata.tEXt_text.add( "Mandelbrot" );
metadata.tEXt_keyword.add( "Comment" );
metadata.tEXt_text.add( "..." );
metadata.tEXt_keyword.add( "MandelbrotCoords" ); // custom keyword
metadata.tEXt_text.add( fractal.getCoords().toString() );           

// Render the PNG to memory
IIOImage iioImage = new IIOImage( image, null, null );
iioImage.setMetadata( metadata ); // Attach the metadata
imagewriter.write( null, iioImage, null );

1
投票

使用Java 1.6,我将Mike的代码编辑为

Node document = domresult.getNode();

代替他的台词

Document document = dom.getResult();

此外,我建议添加一行

writer.dispose()

在完成工作后,释放了作者所拥有的所有资源。


1
投票

我们在JGraphX项目中执行此操作。下载源代码并查看com.mxgraph.util.png包,您将找到三个从Apache Batik源复制的编码类。用法的一个示例是saveXmlPng方法中的com.mxgraph.examples.swing.editor.EditorActions。稍作修改的代码看起来像:

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();
}

[图像是将形成.PNG的BufferedImage,而xml是我们希望在iTxt部分中放置的字符串。 “ mxGraphModel”是该xml字符串的键(该部分包含一些键/值对),显然您可以用键替换它。

也在com.mxgraph.util.png下,我们编写了一个非常简单的类,该类无需处理整个图像即可提取iTxt。您可以使用mxPngEncodeParam.setText而不是setCompressedText()将相同的想法应用于tEXt块,但是压缩的文本部分确实允许使用较大的文本部分。


0
投票

尝试使用Sixlegs Java PNG库(http://sixlegs.com/software/png/)。它声称支持所有块类型,并进行私有块处理。


0
投票

我知道这个问题已经回答了很久,但是,如果您不想在不涉及“ com.sun”层次结构的情况下进行操作,这是一个非常丑陋的示例,因为在其他任何地方都找不到此文档。

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();

0
投票

老问题,但是... PNGJ完全控制了PNG块的读写

© www.soinside.com 2019 - 2024. All rights reserved.