Написание метаданных изображений на Java, предпочтительно PNG

Привет, люди из stackoverflow,

Я потратил некоторое время на поиски решения проблемы, но ничего хорошего не вышло.

Я хотел бы написать метаданные для изображения, которое я создаю с нуля.

Мое понимание Java Advanced Image API заключается в том, что я должен использовать IIOMetadata, но fragmentы кода, которые я нашел, казались слишком сложными.

Затем я обыскал библиотеку и нашел Sanselan, но это кажется немного старым и не очень удобным для написания метаданных.

Я фактически создаю изображение, используя ImageIO.write (изображение, «png», baos);

Я понимаю, что метаданные изображения немного сложны для обработки из-за своей XML-подобной структуры.

Может ли кто-нибудь указать мне учебник, решение, библиотеку …?

Спасибо, Алексис.

Мне приходилось делать то же самое несколько дней назад. Я не нашел точное решение в Интернете, но, глядя на class 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 и class ImageWriter вместе с пакетом ImageIO .

Вы создаете свой объект IIOMetadata , затем getImageWriters для вашего BufferedImage или IIOImage и используете их для write метаданных.

Чтобы добавить к другому ответу, вы также можете попробовать библиотеку PNGJ , у нее есть полная поддержка метаданных.

Кстати, я не понимаю, о чем вы ссылаетесь на структуру XML-подобных метаданных.

Использование метода, опубликованного OP, получает большую часть пути; единственная проблема заключается в том, что PNGMetadata является запатентованной и поэтому вызывает предупреждения компилятора.

Существует способ сделать это без использования проприетарного API, tEXtEntry поиск дерева метаданных для узлов 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); } 
Давайте будем гением компьютера.