用Java编写图像元数据,最好是PNG

你好,来自stackoverflow的人,

我花了一些时间谷歌搜索我的问题的解决方案,但没有什么伟大的出来。

我想将元数据写入我从头开始创建的图像。

我对Java Advanced Image API的理解是我应该使用IIOMetadata,但我发现的代码片段似乎过于复杂。

然后我搜索了一个库并找到了Sanselan,但它看起来有点旧,而且编写元数据并不是很方便。

我实际上使用ImageIO.write创建图像(图像,“png”,baos);

我理解图像metadatas由于其类似XML的结构而有点复杂。

有人能指点我的教程,解决方案,图书馆……?

谢谢Alexis。

几天前我不得不做同样的事情。我还没有找到互联网上的确切解决方案,但是看看com.sun.imageio.plugins.png.PNGMetadata类我可以实现一些结果..

要将自定义元数据写入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(); } 

然后,要读取数据:

 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提供了metadata包和ImageWriter类以及ImageIO包。

您可以为BufferedImageIIOImage创建IIOMetadata对象,然后创建getImageWriters ,并使用它们来write元数据。

要添加到其他答案,您还可以尝试PNGJ库,它具有完整的元数据支持。

顺便说一下,我不明白你所使用的“类似XML”的元数据结构。

使用OP发布的方法可以获得大部分方法; 唯一的问题是PNGMetadata是专有的,因此会导致编译器警告。

通过在元数据树中搜索tEXtEntry节点,有一种方法可以在不使用专有API的情况下执行此操作:

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