2009-04-06 7 views

Odpowiedz

9

Rozwiązanie I uderzyło po po pewnym dekompilacji, wygląda następująco ...

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

Robimy to w projekcie JGraphX. Pobierz kod źródłowy i zajrzyj do pakietu com.mxgraph.util.png, tam znajdziesz trzy klasy do kodowania, które skopiowaliśmy ze źródeł Apache Batik. Przykład użycia znajduje się w com.mxgraph.examples.swing.editor.EditorActions w metodzie saveXmlPng. Nieco edytowany kod wygląda następująco:

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

Jeżeli obraz jest BufferedImage, które będą stanowić .png i xml jest ciąg chcemy umieścić w sekcji iTxt. "mxGraphModel" jest kluczem do tego ciągu xml (sekcja zawiera pewną liczbę par klucz/wartość), oczywiście zamieniasz to na swój klucz.

Również pod com.mxgraph.util.png napisaliśmy naprawdę prostą klasę, która wyodrębnia iTxt bez przetwarzania całego obrazu. Można zastosować ten sam pomysł dla porcji tEXt przy użyciu mxPngEncodeParam.setText zamiast setCompressedText(), ale sekcja skompresowanego tekstu pozwala na znacznie większe sekcje tekstu.

0

Zdaję sobie sprawę, że na to pytanie już dawno odpowiedziano, ale jeśli chcesz to zrobić bez zanurzania się w hierarchii "com.sun", oto krótki i bardzo brzydki przykład, ponieważ nie mogłem znaleźć tego udokumentowanego nigdzie indziej.

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

Korzystanie Java 1.6, edytowany kod Mike'a do

Node document = domresult.getNode(); 

zamiast jego linii

Document document = dom.getResult(); 

Ponadto sugeruję, aby dodać linię

writer.dispose() 

po zakończeniu zadania, tak aby każdy r źródła udostępnione przez autora zostały wydane.

0

Stare pytanie, ale ... PNGJ daje pełną kontrolę na czytanie i pisanie kawałków PNG

Powiązane problemy