Java读写图片XMP元数据XMPMeta(自定义属性信息)

原创
2019/12/09 17:35
阅读数 2.4K
  • 起因

        因项目需要,要求在JPG图片中添加自定义属性信息,在网上找了很久,发现大多数是读取ESIF信息,键值信息都是固定死的,不符合需求,后面找到了com.adobe.xmp类库,也没找到关于XMP数据修改写入生成图片的,不过最后在该处获得了灵感并借鉴了部分代码:https://stackoverflow.com/questions/23253281/reading-jpg-files-xmp-metadata;实现思路:获取图片中的XMP元数据块,添加自定义属性信息,替换XMP数据,生成新的图片的,大功告成

  • 引用
<dependency>
  <groupId>com.adobe.xmp</groupId>
  <artifactId>xmpcore</artifactId>
  <version>6.1.10</version>
</dependency>
  • 编写XMP添加组件类

import com.adobe.internal.xmp.XMPMeta;
import com.adobe.internal.xmp.XMPMetaFactory;
import com.adobe.internal.xmp.impl.XMPIteratorImpl;
import com.adobe.internal.xmp.properties.XMPPropertyInfo;

import java.io.*;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;

/**
 * 图片读取添加XMP数据:
 * 实现思路:获取图片中xmpmeta块信息,编辑替换
 * @author lijiongquan
 */
public class XMPUtil {

    private final byte[] OPEN_ARR = "<x:xmpmeta".getBytes();

    private final byte[] CLOSE_ARR = "</x:xmpmeta>".getBytes();

    private final String namespace = "http://www.xxxx.com.cn/xxxx/1.0/";

    private final String xmpTag = "xxxx:";

    private String orgPath ;

    private String destPath;

    private Map<String, String> xmpMap;

    /**
     * 添加图片XMP数据
     * @param orgPath 图片路径
     * @param destPath 生成图片路径
     * @param xmpMap 添加数据集
     */
    public void changeImgXMP(String orgPath, String destPath, Map<String, String> xmpMap){
        this.orgPath = orgPath;
        this.destPath = destPath;
        this.xmpMap = xmpMap;
        try{
            setXMP();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    private void setXMP()throws Exception{
        File orgFile = new File(orgPath);
        File destFile = new File(destPath);
        if(destFile.exists()){
            destFile.delete();
            destFile.createNewFile();
        }
        FileInputStream in = new FileInputStream(orgFile);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        copy(in, out);
        byte[] fileData = out.toByteArray();
        int openIdx = indexOf(fileData, OPEN_ARR, 0);
        if(openIdx>0){
            int closeIdx = indexOf(fileData, CLOSE_ARR, openIdx + 1) + CLOSE_ARR.length;
            byte[] beforeArr = Arrays.copyOfRange(fileData,0,openIdx);
            byte[] afterArr = Arrays.copyOfRange(fileData,closeIdx+1,fileData.length);
            byte[] xmpArr = Arrays.copyOfRange(fileData,openIdx,closeIdx);
            XMPMeta xmpMeta = XMPMetaFactory.parseFromBuffer(xmpArr);

            XMPMetaFactory.getSchemaRegistry().registerNamespace(namespace,xmpTag);
            addXMPMeta(xmpMeta);

            printXMPMeta(xmpMeta);

            ByteArrayOutputStream xmpOut = new ByteArrayOutputStream();
            XMPMetaFactory.serialize(xmpMeta, xmpOut);
            byte[] xmpArrNew = xmpOut.toByteArray();
            FileOutputStream outputStream = new FileOutputStream(destFile);
            wirteByte(outputStream, beforeArr);
            wirteByte(outputStream, xmpArrNew);
            wirteByte(outputStream, afterArr);
            outputStream.close();
        }
    }

    private void wirteByte(OutputStream out, byte[] bytes) throws Exception{
        out.write(bytes);
        out.flush();
    }

    private void addXMPMeta(XMPMeta xmpMeta) throws Exception{
        Iterator<String> iter = xmpMap.keySet().iterator();
        while (iter.hasNext()){
            String key = iter.next();
            String value = xmpMap.get(key);
            xmpMeta.setProperty(namespace,xmpTag+key,value);
        }
    }

    private void printXMPMeta(XMPMeta xmpMeta) throws Exception{
        XMPIteratorImpl xmpIterator = (XMPIteratorImpl)xmpMeta.iterator();
        while (xmpIterator.hasNext()){
            XMPPropertyInfo obj = (XMPPropertyInfo)xmpIterator.next();
            System.out.println(obj.getNamespace()+"--"+obj.getPath()+"--"+obj.getValue());
        }
    }

    private int indexOf(byte[] arr, byte[] sub, int start){
        int subIdx = 0;
        for(int x = start;x < arr.length;x++) {
            if(arr[x] == sub[subIdx]){
                if(subIdx == sub.length - 1){
                    return x - subIdx;
                }
                subIdx++;
            } else{
                subIdx = 0;
            }
        }
        return -1;
    }

    private void copy(InputStream in, OutputStream out) throws Exception{
        int len = -1;
        byte[] buf = new byte[1024];
        while((len = in.read(buf)) >= 0)
        {
            out.write(buf, 0, len);
        }

        in.close();
        out.close();
    }
}
  • 调用
Map<String, String> xmpMap = new HashMap<>();
xmpMap.put("testKey","testValue");
xmpMap.put("testKey222","testValue22");
XMPUtil xmpUtil = new XMPUtil();
xmpUtil.changeImgXMP("F://4.jpg","F://6.jpg", xmpMap);

 

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
0 收藏
0
分享
返回顶部
顶部