2009-04-06 3 views

risposta

9

La soluzione che ho colpito su dopo un po 'la decompilazione, è la seguente ...

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

Prova la libreria Java Sixlegs PNG (http://sixlegs.com/software/png/). Sostiene di avere il supporto per tutti i tipi di blocco e la gestione privata dei blocchi.

+0

non è che solo per la decodifica? – axel22

0

Facciamo questo nel progetto JGraphX. Scarica il codice sorgente e dai un'occhiata al pacchetto com.mxgraph.util.png, troverai tre classi per la codifica che abbiamo copiato dalle fonti di Apache Batik. Un esempio di utilizzo è in com.mxgraph.examples.swing.editor.EditorActions nel metodo saveXmlPng. Leggermente modificato il codice è simile:

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

dove l'immagine è l'BufferedImage che formeranno il .PNG e XML è la stringa che vogliamo inserire nella sezione iTxt. "mxGraphModel" è la chiave per quella stringa xml (la sezione comprende un certo numero di coppie chiave/valore), ovviamente la sostituisci con la tua chiave.

Anche in com.mxgraph.util.png abbiamo scritto una classe molto semplice che estrae l'iTxt senza elaborare l'intera immagine. È possibile applicare la stessa idea per il blocco tEXt usando mxPngEncodeParam.setText anziché setCompressedText(), ma la sezione di testo compresso consente sezioni di testo molto più grandi.

0

Mi rendo conto che questa domanda è stata da tempo risposta, ma se si vuole farlo senza immergersi nella gerarchia "com.sun", ecco un esempio rapido e molto brutto in quanto non è stato possibile trovare questo documento altrove.

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

Utilizzo di Java 1.6, ho modificato il codice di Mike per

Node document = domresult.getNode(); 

al posto della sua linea

Document document = dom.getResult(); 

Inoltre, io suggerirei di aggiungere una riga

writer.dispose() 

dopo che il lavoro è stato fatto, in modo che qualsiasi r le risorse possedute dallo scrittore vengono rilasciate.

0

vecchia questione, ma ... PNGJ dà il controllo completo per la lettura e la scrittura di pezzi PNG