Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing image metadata in Java, preferably PNG

I would like to write metadata to a PNG image that I create.

My understanding of Java Advanced Image API is that I should use IIOMetadata, but code snippets I found seem overly complicated. Then I searched for a library and found Sanselan but it seems a bit old, and not very handy for writing metadata.

To actually create the image, I use

ImageIO.write(image, "png", baos);

I understand image metadatas are complex to handle due to its XML-like structure. Could anybody point me to a tutorial, solution, or library that will help?

like image 415
Alexis Laporte Avatar asked Jun 27 '11 15:06

Alexis Laporte


People also ask

Does PNG support metadata?

PNG has no EXIF chunk. Thus EXIF metadata will get lost if you convert from JPEG into PNG. However Adobe has made XMP for storing all kinds of metadata. So that you can convert between JPEG and PNG while preserving metadata.


2 Answers

I had to do the the same thing some days ago.. I have not found the exact solution on the internet either but looking at the com.sun.imageio.plugins.png.PNGMetadata class I could achieve some results..

To write a custom metadata to a PNG file:

public byte[] writeCustomData(BufferedImage buffImg, String key, String value) throws Exception {
    ImageWriter writer = ImageIO.getImageWritersByFormatName("png").next();

    ImageWriteParam writeParam = writer.getDefaultWriteParam();
    ImageTypeSpecifier typeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB);

    //adding metadata
    IIOMetadata metadata = writer.getDefaultImageMetadata(typeSpecifier, writeParam);

    IIOMetadataNode textEntry = new IIOMetadataNode("tEXtEntry");
    textEntry.setAttribute("keyword", key);
    textEntry.setAttribute("value", value);

    IIOMetadataNode text = new IIOMetadataNode("tEXt");
    text.appendChild(textEntry);

    IIOMetadataNode root = new IIOMetadataNode("javax_imageio_png_1.0");
    root.appendChild(text);

    metadata.mergeTree("javax_imageio_png_1.0", root);

    //writing the data
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ImageOutputStream stream = ImageIO.createImageOutputStream(baos);
    writer.setOutput(stream);
    writer.write(metadata, new IIOImage(buffImg, null, metadata), writeParam);
    stream.close();

    return baos.toByteArray();
}

Then, to read the data:

public String readCustomData(byte[] imageData, String key) throws IOException{
    ImageReader imageReader = ImageIO.getImageReadersByFormatName("png").next();

    imageReader.setInput(ImageIO.createImageInputStream(new ByteArrayInputStream(imageData)), true);

    // read metadata of first image
    IIOMetadata metadata = imageReader.getImageMetadata(0);

    //this cast helps getting the contents
    PNGMetadata pngmeta = (PNGMetadata) metadata; 
    NodeList childNodes = pngmeta.getStandardTextNode().getChildNodes();

    for (int i = 0; i < childNodes.getLength(); i++) {
        Node node = childNodes.item(i);
        String keyword = node.getAttributes().getNamedItem("keyword").getNodeValue();
        String value = node.getAttributes().getNamedItem("value").getNodeValue();
        if(key.equals(keyword)){
            return value;
        }
    }
    return null;
}
like image 111
Rogel Garcia Avatar answered Sep 19 '22 09:09

Rogel Garcia


Java provides the metadata package and the ImageWriter class along with the ImageIO package.

You create your IIOMetadata object, then getImageWriters for your BufferedImage or IIOImage and use them to write the metadata.

like image 45
c00kiemon5ter Avatar answered Sep 22 '22 09:09

c00kiemon5ter