Написание метаданных изображения на Java, желательно PNG - PullRequest
17 голосов
/ 27 июня 2011

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

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

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

Я понимаю, что Java Advanced Image API - это то, что я должен использовать IIOMetadata, но фрагменты кода, которые я нашел, кажутся слишком сложными.

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

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

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

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

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

Ответы [ 4 ]

25 голосов
/ 05 января 2012

Мне пришлось сделать то же самое несколько дней назад .. Я не нашел точного решения в интернете, но, глядя на класс 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;
}
1 голос
/ 27 июня 2011

Java предоставляет пакет metadata и класс ImageWriter вместе с пакетом ImageIO.

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

0 голосов
/ 16 марта 2018

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

Существует способ сделать это без использования проприетарного API путем поиска в дереве метаданных tEXtEntry узлов:

private List<Node> findNodesWithName(String name, Node root) {
    List<Node> 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<Node> 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);
}
0 голосов
/ 27 июня 2011

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...