2009-04-06 12 views

Respuesta

9

La solución que llamó la atención sobre después de algún descompilación, es como sigue ...

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

buscar en la biblioteca de Java Sixlegs PNG (http://sixlegs.com/software/png/). Afirma tener soporte para todos los tipos de fragmentos y maneja los fragmentos privados.

+0

no es que sólo para la decodificación? – axel22

0

Hacemos esto en el proyecto JGraphX. Descargue el código fuente y eche un vistazo al paquete com.mxgraph.util.png, allí encontrará tres clases de codificación que copiamos de las fuentes de Apache Batik. Un ejemplo de uso es en com.mxgraph.examples.swing.editor.EditorActions en el método saveXmlPng. Ligeramente editado el código es el siguiente:

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

Cuando la imagen es la BufferedImage que formará el PNG y XML es la cadena que queremos colocar en la sección iTxt. "mxGraphModel" es la clave para esa cadena xml (la sección comprende un cierto número de pares clave/valor), obviamente usted reemplaza eso con su clave.

También en com.mxgraph.util.png hemos escrito una clase muy simple que extrae el iTxt sin procesar toda la imagen. Puede aplicar la misma idea para el fragmento tEXt utilizando mxPngEncodeParam.setText en lugar de setCompressedText(), pero la sección de texto comprimido permite secciones de texto considerablemente mayores.

0

Me doy cuenta de que esta pregunta ha sido respondida hace mucho tiempo, pero si quieres hacerlo sin sumergirte en la jerarquía "com.sun", aquí hay un ejemplo rápido y desagradable ya que no pude encontrarlo documentado en ningún otro lado.

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

Uso de Java 1.6, que edité código de Mike para

Node document = domresult.getNode(); 

en lugar de su línea

Document document = dom.getResult(); 

Por otra parte, me gustaría sugerir que añadir una línea

writer.dispose() 

después de que el trabajo haya sido hecho, de modo que cualquier r se liberan los recursos que posee el escritor.

0

vieja pregunta, pero ... PNGJ permite un control total para la lectura y la escritura trozos PNG

Cuestiones relacionadas