2009-04-06 14 views
10

Tôi hiện đang sử dụng javax.imageio.ImageIO để ghi tệp PNG. Tôi muốn bao gồm một đoạn tEXt (và thực sự là bất kỳ đoạn nào listed here), nhưng có thể thấy không có phương tiện làm như vậy.Tôi làm cách nào để lưu PNG với đoạn tEXt hoặc iTXt từ Java?

Bằng giao diện com.sun.imageio.plugins.png.PNGMetadata, điều đó có thể thực hiện được.

Tôi nên biết ơn nhất về bất kỳ đầu mối hoặc câu trả lời nào.

M.

Trả lời

9

Các giải pháp tôi tấn công khi sau một decompilation, diễn ra như sau ...

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

Thử thư viện PNG Java sáu lần (http://sixlegs.com/software/png/). Nó tuyên bố có hỗ trợ cho tất cả các loại chunk và không xử lý tin riêng.

+0

Mà không phải là chỉ để giải mã? – axel22

0

Chúng tôi làm điều này trong dự án JGraphX. Tải về mã nguồn và có một cái nhìn trong gói com.mxgraph.util.png, ở đó bạn sẽ tìm thấy ba lớp mã hóa mà chúng ta đã sao chép từ các nguồn Apache Batik. Một ví dụ về cách sử dụng nằm trong com.mxgraph.examples.swing.editor.EditorActions trong phương thức saveXmlPng. Hơi chỉnh sửa mã trông giống như:

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

Ảnh ở đâu là BufferedImage sẽ tạo thành .PNG và xml là chuỗi chúng tôi muốn đặt trong phần iTxt. "mxGraphModel" là khóa cho chuỗi xml đó (phần bao gồm một số cặp khóa/giá trị), rõ ràng là bạn thay thế bằng khóa của mình.

Cũng theo com.mxgraph.util.png, chúng tôi đã viết một lớp thực sự đơn giản để trích xuất iTxt mà không cần xử lý toàn bộ hình ảnh. Bạn có thể áp dụng cùng một ý tưởng cho đoạn tEXt bằng cách sử dụng mxPngEncodeParam.setText thay vì setCompressedText(), nhưng phần văn bản đã nén không cho phép các phần văn bản lớn hơn đáng kể.

0

Tôi nhận ra câu hỏi này được trả lời từ lâu, nhưng nếu bạn muốn làm điều đó mà không nhúng vào phân cấp "com.sun", đây là ví dụ nhanh và rất xấu vì tôi không thể tìm thấy tài liệu này ở bất kỳ nơi nào khác.

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

Sử dụng Java 1.6, tôi thay đổi nội dung đang Mike để

Node document = domresult.getNode(); 

thay vì dòng mình

Document document = dom.getResult(); 

Hơn nữa, tôi muốn đề nghị thêm một dòng

writer.dispose() 

sau khi công việc đã được thực hiện, để bất kỳ r esources được tổ chức bởi các nhà văn được phát hành.

0

Cũ câu hỏi, nhưng ... PNGJ cho phép kiểm soát đầy đủ cho việc đọc và viết khối PNG

Các vấn đề liên quan