最近项目里面涉及到了图片的元数据修改,这里把详细的内容给大家分享一下
项目用到了两个Jar包,分别是 mediautil-1.0.jar,metadata-extractor-2.3.1.jar。
重点是mediautil这个jar包,附上它的官方链接:http://mediachest.sourceforge.net/mediautil/,里面有一些它的官方示例,有一点需要注意的是,官网有一个更新补丁,我们需要将补丁包下载解压缩之后放入我们的项目
后续在进行EXIF信息修改的java类中引用刚刚解压好的文件。
下面附上一段完整的修改图片EXif信息代码
package com.test;
import mediautil.gen.Rational;
import mediautil.image.jpeg.Entry;
import mediautil.image.jpeg.Exif;
import mediautil.image.jpeg.IFD;
import mediautil.image.jpeg.LLJTran;
import java.io.*;
/**
* 重写照片EXIF信息
*
* @author gzy
* 2022.05.20
*/
public class Test {
public static void main(String[] args) throws Exception {
main1();
}
public static void main1() throws Exception {
InputStream fip = new FileInputStream("C:\\1.jpg");
LLJTran llj = new LLJTran(fip);
llj.read(LLJTran.READ_INFO, true);
//这里是重点,网上很多人出现 mediautil.image.jpeg.JPEG cannot be cast to mediautil.image.jpeg.Exif 这个错误,原因是这张图片没有Exif头,需要给他初始化一个
if (!(llj.getImageInfo() instanceof Exif)) {
llj.addAppx(LLJTran.dummyExifHeader, 0,
LLJTran.dummyExifHeader.length, true);
}
Exif exif = (Exif) llj.getImageInfo();
//获取基础标签
IFD mainIfd = exif.getIFDs()[0];
//设置相机制造商
Entry e = new Entry(Exif.ASCII);
e.setValue(0, "leica");
mainIfd.addEntry(Exif.MAKE, e);
//设置相机型号
e = new Entry(Exif.ASCII);
e.setValue(0, "leica");
mainIfd.addEntry(Exif.MODEL, e);
//设置描述
e = new Entry(Exif.ASCII);
e.setValue(0, "xxx");
mainIfd.addEntry(Exif.IMAGEDESCRIPTION, e);
//版权
e = new Entry(Exif.ASCII);
e.setValue(0, "xxx");
mainIfd.addEntry(Exif.COPYRIGHT, e);
//获取私有标签
IFD exifOffSetId = mainIfd.getIFD(Exif.EXIFOFFSET);
if (exifOffSetId == null) {
exifOffSetId = new IFD(Exif.EXIFOFFSET, Exif.LONG);
mainIfd.addIFD(exifOffSetId);
}
exifOffSetId.setEntry(Exif.DATETIMEORIGINAL, 0, e);
e = new Entry(Exif.RATIONAL);
e.setValue(0, new Rational(1, 250));
exifOffSetId.setEntry(Exif.EXPOSURETIME, 0, e);
//修改图片光圈值
e = new Entry(Exif.RATIONAL);
e.setValue(0, new Rational(16, 14));
exifOffSetId.setEntry(Exif.APERTUREVALUE, 0, e);
//修改图片ISO速度
e = new Entry(Exif.SHORT);
e.setValue(0, 200);
exifOffSetId.setEntry(Exif.ISOSPEEDRATINGS, 0, e);
//修改图片焦距
e = new Entry(Exif.RATIONAL);
e.setValue(0, new Rational(50, 1));
exifOffSetId.setEntry(Exif.FOCALLENGTH, 0, e);
//修改图片35毫米焦距
e = new Entry(Exif.SHORT);
e.setValue(0, 50);
exifOffSetId.setEntry(Exif.FOCALLENGTHIN35MMFILM, 0, e);
//修改目标距离
e = new Entry(Exif.RATIONAL);
e.setValue(0, new Rational(5, 10));
exifOffSetId.setEntry(Exif.SUBJECTDISTANCE, 0, e);
//修改图片闪光能量值
e = new Entry(Exif.RATIONAL);
e.setValue(0, new Rational(7800, 1));
exifOffSetId.setEntry(Exif.FLASHENERGY, 0, e);
//修改图片亮度
e = new Entry(Exif.SHORT);
e.setValue(0, 7);
exifOffSetId.setEntry(Exif.BRIGHTNESSVALUE, 0, e);
//修改图片光源
e = new Entry(Exif.SHORT);
e.setValue(0, 0);
exifOffSetId.setEntry(Exif.LIGHTSOURCE, 0, e);
//修改图片白平衡
e = new Entry(Exif.SHORT);
e.setValue(0, 0);
exifOffSetId.setEntry(Exif.EXPOSUREMODE, 0, e);
//修改图曝光程序
e = new Entry(Exif.SHORT);
e.setValue(0, 2);
exifOffSetId.setEntry(Exif.EXPOSUREPROGRAM, 0, e);
//修改图清晰度
e = new Entry(Exif.SHORT);
e.setValue(0, 2);
exifOffSetId.setEntry(Exif.SHARPNESS, 0, e);
//修改图像饱和度
e = new Entry(Exif.SHORT);
e.setValue(0, 0);
exifOffSetId.setEntry(Exif.SATURATION, 0, e);
//修改图像对比度
e = new Entry(Exif.SHORT);
e.setValue(0, 0);
exifOffSetId.setEntry(Exif.CONTRAST, 0, e);
//修改图像Exif版本
e = new Entry(Exif.ASCII);
e.setValue(0, "0230");
exifOffSetId.setEntry(Exif.EXIFVERSION, 0, e);
//获取GPS标签
IFD gpsIfd = mainIfd.getIFD(Exif.GPSINFO);
if (gpsIfd == null) {
System.out.println("Gps IFD not found adding..");
gpsIfd = new IFD(Exif.GPSINFO, Exif.LONG);
mainIfd.addIFD(gpsIfd);
}
//修改图片GPS信息
e = new Entry(Exif.ASCII);
e.setValue(0, 'N');
gpsIfd.setEntry(new Integer(Exif.GPSLatitudeRef), 0, e);
e = new Entry(Exif.RATIONAL);
e.setValue(0, new Rational(45, 1));
e.setValue(1, new Rational(39786653, 100000));
e.setValue(2, new Rational(0, 1));
gpsIfd.setEntry(new Integer(Exif.GPSLatitude), 0, e);
e = new Entry(Exif.ASCII);
e.setValue(0, 'E');
gpsIfd.setEntry(new Integer(Exif.GPSLongitudeRef), 0, e);
e = new Entry(Exif.RATIONAL);
e.setValue(0, new Rational(87, 1));
e.setValue(1, new Rational(116562968, 100000));
e.setValue(2, new Rational(0, 1));
gpsIfd.setEntry(new Integer(Exif.GPSLongitude), 0, e);
llj.refreshAppx(); // Recreate Marker Data for changes done
// 改写后的文件
String fileName = "C:\\test5.jpg";
OutputStream out = new BufferedOutputStream(new FileOutputStream(fileName));
llj.xferInfo(null, out, LLJTran.REPLACE, LLJTran.REPLACE);
fip.close();
out.close();
llj.freeMemory();
}
}
图片相关信息修改的对照表附上链接 https://www.awaresystems.be/imaging/tiff/tifftags/baseline.html
不同的exif信息是存放在不同的exif tag里面的,所以修改的方式不一样,具体的所属标签可以去对照表里面查看,下面是一些比较常用的标签获取代码,具体的一些其他标签可以在上面链接里面查找
//获取基本标签
IFD mainIfd = exif.getIFDs()[0];
//获取Exif私有标签
IFD exifOffSetId = mainIfd.getIFD(Exif.EXIFOFFSET);
//获取GPS标签
IFD gpsIfd = mainIfd.getIFD(Exif.GPSINFO);
上面是一些基本的属性,它的Hex分别一一对应Exif.java里面的静态变量
比如相机型号Model:下面是Exif.java对应的变量
/** Identifies the MODEL tag */
public final static int MODEL = 0x110;
图片里是相机型号在元数据里的对照信息,Type是它对应编码,下面是基本写法
//获取基本标签
IFD mainIfd = exif.getIFDs()[0];
//设置编码类型
Entry e = new Entry(Exif.ASCII);
//设置值
e.setValue(0, "leica");
//给标签内容赋值
mainIfd.addEntry(Exif.MODEL, e);
具体的图片信息修改可以参考下贴出来的完整代码 ,其他的一些Exif读取,缩略图修改大家可以去看看MediaUtil的官方示例