我目前正在使用javax.imageio.ImageIO来编写PNG文件。我想要包含一个tEXt块(实际上是任何块listed here),但是看不到这样做。
通过com.sun.imageio.plugins.png.PNGMetadata的外观,它应该是可能的。
我应该非常感谢任何线索或答案。
微米。
答案 0 :(得分: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 :(得分:1)
使用Java 1.6,我将Mike的代码编辑为
Node document = domresult.getNode();
而不是他的行
Document document = dom.getResult();
此外,我建议添加一行
writer.dispose()
作业完成后,以便释放作者所持有的任何资源。
答案 2 :(得分:0)
尝试Sixlegs Java PNG库(http://sixlegs.com/software/png/)。 它声称支持所有块类型并进行私有块处理。
答案 3 :(得分:0)
我们在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();
}
其中image是将形成.PNG的BufferedImage,而xml是我们希望放置在iTxt部分中的字符串。 “mxGraphModel”是该xml字符串的键(该部分包含一些键/值对),显然您可以用键替换它。
同样在com.mxgraph.util.png下,我们编写了一个非常简单的类,它可以在不处理整个图像的情况下提取iTxt。您可以使用mxPngEncodeParam.setText而不是setCompressedText()对tEXt块应用相同的想法,但压缩文本部分允许相当大的文本部分。
答案 4 :(得分: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();
答案 5 :(得分:0)
老问题,但...... PNGJ完全控制了读写PNG块