私は現在 javax.imageio.ImageIO を使用して PNG ファイルを書き込んでいます。tEXt チャンク (実際には、ここにリストされているチャンクのいずれか) を含めたいのですが、そうする方法がわかりません。
com.sun.imageio.plugins.png.PNGMetadata の見た目から、それは可能であるはずです。
手がかりや答えに最も感謝する必要があります。
M.
私は現在 javax.imageio.ImageIO を使用して PNG ファイルを書き込んでいます。tEXt チャンク (実際には、ここにリストされているチャンクのいずれか) を含めたいのですが、そうする方法がわかりません。
com.sun.imageio.plugins.png.PNGMetadata の見た目から、それは可能であるはずです。
手がかりや答えに最も感謝する必要があります。
M.
いくつかの逆コンパイルの後に私が思いついた解決策は、次のようになります...
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 );
これは、JGraphXプロジェクトで行います。ソースコードをダウンロードしてcom.mxgraph.util.pngパッケージを見ると、ApacheBatikソースからコピーしたエンコーディング用の3つのクラスがあります。使用例は、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を抽出する非常に単純なクラスを作成しました。setCompressedText()の代わりにmxPngEncodeParam.setTextを使用してtEXtチャンクに同じアイデアを適用できますが、圧縮されたテキストセクションではかなり大きなテキストセクションを使用できます。
この質問には長い間答えられていませんでしたが、「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();
Java 1.6 を使用して、Mike のコードを次のように編集しました。
Node document = domresult.getNode();
彼のセリフの代わりに
Document document = dom.getResult();
さらに、行を追加することをお勧めします
writer.dispose()
ジョブが完了した後、ライターが保持していたリソースが解放されます。
Sixlegs Java PNGライブラリ(http://sixlegs.com/software/png/)を試してください。すべてのチャンクタイプをサポートしていると主張し、プライベートチャンク処理を行います。
古い質問ですが... PNGJはPNGチャンクの読み書きを完全に制御します