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

2022-09-02 12:42:57

我想将元数据写入我创建的 PNG 图像。

我对Java高级图像API的理解是我应该使用,但是我发现的代码片段似乎过于复杂。然后我搜索了一个图书馆,找到了Sanselan,但它似乎有点旧,而且对于编写元数据来说不是很方便。IIOMetadata

为了实际创建图像,我使用

ImageIO.write(image, "png", baos);

我知道图像元数据由于其类似XML的结构而处理起来很复杂。任何人都可以向我指出一个教程,解决方案或库,这将有所帮助吗?


答案 1

几天前我不得不做同样的事情。我也没有在互联网上找到确切的解决方案,但看着课程,我可以取得一些成果。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;
}

答案 2

Java 提供元数据包和 ImageWriter 类以及 ImageIO 包。

创建 IIOMetadata 对象,然后为 BufferedImageIIOImage 创建对象,并将它们用于元数据。getImageWriterswrite


推荐