我目前正在使用javax.imageio.ImageIO编写PNG文件。我想包括一个tEXt块(以及实际上任何块listed here),但看不到这样做的任何方法。
通过com.sun.imageio.plugins.png.PNGMetadata的外观,应该可以。
我应该对任何线索或答案深表谢意。
男
经过一些反编译后,我遇到的解决方案如下...
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 );
使用Java 1.6,我将Mike的代码编辑为
Node document = domresult.getNode();
代替他的台词
Document document = dom.getResult();
此外,我建议添加一行
writer.dispose()
在完成工作后,释放了作者所拥有的所有资源。
我们在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块,但是压缩的文本部分确实允许使用较大的文本部分。
尝试使用Sixlegs Java PNG库(http://sixlegs.com/software/png/)。它声称支持所有块类型,并进行私有块处理。
我知道这个问题已经回答了很久,但是,如果您不想在不涉及“ 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();
老问题,但是... PNGJ完全控制了PNG块的读写