Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java ImageIO, unable to change metadata tree

I'm trying to use ImageIO to change the JPEG Comment field (COM) of a file. I read the metadata, do some changes to the DOM (change attribute of the comment field), then save / print the metadata. But my changes are not shown. This is the code (in a simple test class with static main()), 'file' is set.

        ImageWriter writer = ImageIO.getImageWritersBySuffix("jpeg").next();
        ImageReader reader = ImageIO.getImageReader(writer);

        reader.setInput(new FileImageInputStream(file));

        RenderedImage img = reader.read(0);
        IIOMetadata meta = reader.getImageMetadata(0);


        IIOMetadataNode root1 = (IIOMetadataNode) meta.getAsTree("javax_imageio_jpeg_image_1.0");
        String comment1 = getCommentFromDOM(root1);
        System.out.println("comment 1 = " + comment1);

        String comment2 = getCommentFromDOM(root1);
        System.out.println("comment 2 = " + comment2);


        meta.setFromTree("javax_imageio_jpeg_image_1.0", root1);
        //meta.reset();


        IIOMetadataNode root2 = (IIOMetadataNode) meta.getAsTree("javax_imageio_jpeg_image_1.0");
        String comment3 = getCommentFromDOM(root2);
        System.out.println("comment 3 = " + comment3);

The method getCommentFromDOM() just goes trough the tree and gets the comment attribute in the com tag, and then it changes the comment field but returns the original value.

             ...
                if(md.getNodeName().equalsIgnoreCase("com")) {
                    String comment = md.getAttribute("comment");
                    md.setAttribute("comment", "FOOOOOOOOOO");
                    return comment;
                }
             ...

So when this program is executed it will output:

  comment 1 = originalcomment
  comment 2 = FOOOOOOOOOOO
  comment 3 = originalcomment

So the DOM was changed, but it looks like the meta.setFromTree() method did not use the new tree. I've also tried running meta.reset() which should clear the metadata, but that also seems to have no effect on the meta object.

Can anyone see what I've done wrong in this very simple ImageIO test?

like image 897
klogd Avatar asked Jan 01 '26 05:01

klogd


1 Answers

nowaq's answer got me started in the right direction, but I was having trouble handling the case where the original image did not have an existing comment (his solution works in case the original already has a comment). The following code works for me in both cases:

Element tree = (Element) imageMetadata.getAsTree("javax_imageio_jpeg_image_1.0");
NodeList comNL = tree.getElementsByTagName("com");
IIOMetadataNode comNode;
if (comNL.getLength() == 0) {
    comNode = new IIOMetadataNode("com");
    Node markerSequenceNode = tree.getElementsByTagName("markerSequence").item(0);
    markerSequenceNode.insertBefore(comNode,markerSequenceNode.getFirstChild());
} else {
    comNode = (IIOMetadataNode) comNL.item(0);
}
comNode.setUserObject(("YourComment").getBytes("ISO-8859-1"));
imageMetadata.setFromTree("javax_imageio_jpeg_image_1.0", tree);
like image 82
Jo Jo Avatar answered Jan 02 '26 19:01

Jo Jo