2009-04-06 5 views
10

В настоящее время я использую javax.imageio.ImageIO для записи PNG-файла. Я хотел бы включить кусок tEXt (и даже любой из кусков listed here), но не вижу средств для этого.Как сохранить PNG с помощью фрагмента tEXt или iTXt с Java?

По внешнему виду com.sun.imageio.plugins.png.PNGMetadata это должно быть возможно.

Я должен быть благодарен за любые подсказки или ответы.

М.

ответ

9

Решение, которое я ударил по прошествии некоторого декомпиляции, идет следующим образом ...

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

Попробуйте библиотеку Sixlegs Java PNG (http://sixlegs.com/software/png/). Он утверждает, что имеет поддержку всех типов блоков и делает частную обработку куска.

+0

не то, что только для декодирования? – axel22

0

Мы делаем это в проекте JGraphX. Загрузите исходный код и посмотрите в пакете com.mxgraph.util.png, там вы найдете три класса для кодирования, которые мы скопировали из источников Apache Batik. Пример использования - в com.mxgraph.examples.swing.editor.EditorActions в методе saveXmlPng. Слегка отредактированный код выглядит следующим образом:

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

Где изображение является BufferedImage, который будет формировать .PNG и XML является строка, которую мы хотим разместить в разделе iTxt. «mxGraphModel» является ключом для этой строки xml (раздел содержит некоторое количество пар ключ/значение), очевидно, вы заменяете это на свой ключ.

Также в com.mxgraph.util.png мы написали действительно простой класс, который извлекает iTxt без обработки всего изображения. Вы можете применить ту же идею для фрагмента tEXt, используя mxPngEncodeParam.setText вместо setCompressedText(), но сжатый текстовый раздел позволяет значительно увеличить текстовые разделы.

0

Я понимаю, что этот вопрос уже давно ответил, но если вы хотите сделать это, не погрузившись в иерархию «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(); 
1

Использование Java 1.6, я редактировал код Майка в

Node document = domresult.getNode(); 

вместо его линии

Document document = dom.getResult(); 

Кроме того, я хотел бы предложить, чтобы добавить строку

writer.dispose() 

после того, как работа выполнена, так что любое r выпущенные автором писатели.

0

Старый вопрос, но ... PNGJ дает полный контроль для чтения и записи PNG ломтей

 Смежные вопросы

  • Нет связанных вопросов^_^