Scrivere i metadati delle immagini in Java, preferibilmente PNG

Salve gente da StackOverflow,

Ho passato un po ‘di tempo a cercare su Google una soluzione al mio problema, ma non è uscito nulla di eccezionale.

Mi piacerebbe scrivere metadati su un’immagine che creo da zero.

La mia comprensione dell’API di Java Advanced Image è che dovrei usare IIOMetadata ma frammenti di codice che ho trovato sembravano essere eccessivamente complicati.

Poi ho cercato in una biblioteca e ho trovato Sanselan, ma sembra un po ‘vecchio, e non molto utile per scrivere i metadati.

    In realtà creo l’immagine usando ImageIO.write (image, “png”, baos);

    Capisco che i metadati delle immagini sono un po ‘complessi da gestire a causa della sua struttura simile a XML.

    Qualcuno potrebbe indicarmi un tutorial, una soluzione, una biblioteca …?

    Grazie, Alexis.

    Ho dovuto fare la stessa cosa qualche giorno fa .. Non ho trovato la soluzione esatta su Internet, ma guardando la class com.sun.imageio.plugins.png.PNGMetadata ho potuto ottenere alcuni risultati ..

    Per scrivere metadati personalizzati in un file PNG:

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

    Quindi, per leggere i dati:

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

    Java fornisce il pacchetto di metadata e la class ImageWriter insieme al pacchetto ImageIO .

    IIOMetadata tuo object IIOMetadata , quindi getImageWriters per BufferedImage o IIOImage e li usi per write i metadati.

    Per aggiungere ad altre risposte, puoi anche provare la libreria PNGJ , ha pieno supporto per i metadati.

    A proposito, non capisco a cosa ti riferisci con la struttura “metrica” ​​dei metadati.

    Usando il metodo pubblicato da OP, la maggior parte del modo lì; l’unico problema è che PNGMetadata è proprietario e quindi causa avvisi del compilatore.

    Esiste un metodo per farlo senza utilizzare l’API proprietaria, eseguendo una ricerca nell’albero dei metadati per i nodes tEXtEntry :

     private List findNodesWithName(String name, Node root) { List found = new ArrayList<>(); Node n = root.getFirstChild(); while (n != null) { if (n.getNodeName().equals(name)) { found.add(n); } found.addAll(findNodesWithName(name, n)); n = n.getNextSibling(); } } // ... // To use it: IIOMetadata metadata = ...; List tEXtNodes = findNodesWithName( "tEXtEntry", metadata.getAsTree(metadata.getNativeMetadataFormatName())); for (Node n : tEXtNodes) { String keyword = node.getAttributes().getNamedItem("keyword"); String value = node.getAttributes().getNamedItem("value"); System.out.println("keyword: " + keyword + "; value: " + value); }