该库能了解多种格式的元数据,其中许多可以存在于单个图像:
Exif、IPTC、XMP、JFIF / JFXX、ICC Profiles、Photoshop fields、PNG properties、BMP properties、GIF properties
它能处理类型的文件:JPEG、TIFF、PSD、PNG、BMP、GIF、Camera Raw (NEF/CR2/ORF/ARW/RW2/…)
注:并不是每个JPG图像文件都包含有EXIF信息,你可以在Windows资源管理器单击选中图片后,如果该图片包含EXIF信息,则在窗口状态栏会显示出相机的型号。
二、示例代码及描述
=========
下面我们给出一些代码将含有EXIF的图片信息全部打印出来。
示例1):
import java.io.File;
import java.util.Iterator;
import com.drew.imaging.jpeg.JpegMetadataReader;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.Tag;
import com.drew.metadata.exif.ExifDirectory;
/**
*/
public class ExifTest {
public static void main(String[] args) throws Exception {
//包含EXIF信息的图片地址
File jpegFile = new File(“D:\XXXX\XXXX\XXXX.JPG”);
Metadata metadata = JpegMetadataReader.readMetadata(jpegFile);
Directory exif = metadata.getDirectory(ExifDirectory.class);
Iterator tags = exif.getTagIterator();
while (tags.hasNext()) {
Tag tag = (Tag)tags.next();
System.out.println(tag);
}
}
}
示例2:)
public static void main(String[] args) throws Exception {
File mFile = new File(“F:/XXX.JPG”);
Metadata metadata = ImageMetadataReader.readMetadata(mFile);
for (Directory directory : metadata.getDirectories()) {
if(“ExifSubIFDDirectory”.equalsIgnoreCase( directory.getClass().getSimpleName() )){
//光圈F值=镜头的焦距/镜头光圈的直径
System.out.println(“光圈值: f/” + directory.getString(ExifSubIFDDirectory.TAG_FNUMBER) );
System.out.println("曝光时间: " + directory.getString(ExifSubIFDDirectory.TAG_EXPOSURE_TIME)+ “秒” );
System.out.println("ISO速度: " + directory.getString(ExifSubIFDDirectory.TAG_ISO_EQUIVALENT) );
System.out.println("焦距: " + directory.getString(ExifSubIFDDirectory.TAG_FOCAL_LENGTH) + “毫米” );
System.out.println("拍照时间: " + directory.getString(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL) );
System.out.println("宽: " + directory.getString(ExifSubIFDDirectory.TAG_EXIF_IMAGE_WIDTH) );
System.out.println("高: " + directory.getString(ExifSubIFDDirectory.TAG_EXIF_IMAGE_HEIGHT) );
}
if(“ExifIFD0Directory”.equalsIgnoreCase( directory.getClass().getSimpleName() )){
System.out.println("照相机制造商: " + directory.getString(ExifIFD0Directory.TAG_MAKE) );
System.out.println("照相机型号: " + directory.getString(ExifIFD0Directory.TAG_MODEL) );
System.out.println("水平分辨率: " + directory.getString(ExifIFD0Directory.TAG_X_RESOLUTION) );
System.out.println("垂直分辨率: " + directory.getString(ExifIFD0Directory.TAG_Y_RESOLUTION) );
}
}
}
示例3):
File mFilePath=“C://XXX.jpg”;
Metadata metadata = com.drew.imaging.jpeg.JpegMetadataReader.readMetadata(mFilePath);
JpegDirectory jd = (JpegDirectory)metadata.getDirectory(JpegDirectory.class);
System.out.println("------------" + jd.getImageHeight()); //图片的高
System.out.println("------------" + jd.getImageWidth()); //图片的宽
//由于只是读取图片的头信息,所以无论多大的图片都能读取,而且速度很快.
从执行的中可以看到照片的详细拍摄时间,拍摄用的相机型号,曝光时间,光圈值,焦距,ISO值 等等。
你也可以直接指定读取其中任意参数的值,ExifDirectory 类中定义了很多以 TAG_ 开头的整数常量,这些常量代表特定的一个参数值,例如要读取相机的型号,可以用下面代码来获取。
Metadata metadata = JpegMetadataReader.readMetadata(jpegFile);
Directory exif = metadata.getDirectory(ExifDirectory.class);
String model = exif.getString(ExifDirectory.TAG_MODEL);
上述提到的是如何获取照片的EXIF信息,其中包含一个很重要的信息就是——拍摄方向。例如所用的图片拍摄方向是:Orientation - Top, left side (Horizontal / normal)。我们在拍照的时候经常会根据场景的不同来选择相机的方向,例如拍摄一颗高树,我们会把相机竖着拍摄,使景物刚好适合整个取景框,但是这样得到的图片如果用普通的图片浏览器看便是倒着的,需要调整角度才能得到一个正常的图像。
通过读取图片的EXIF信息,可以得到关于拍摄方向的这样一个结果:Orientation - Left side, bottom (Rotate 270 CW)。
而直接读取 ExitDirectory.TAG_ORIENTATION 标签的值是8。
来看下这个项目是如何来定义这些返回值的,打开源码包中的ExifDescriptor类的getOrientationDescription(),该方法代码如下:
public String getOrientationDescription() throws MetadataException{
if (!_directory.containsTag(ExifDirectory.TAG_ORIENTATION)) return null;
int orientation = _directory.getInt(ExifDirectory.TAG_ORIENTATION);
switch (orientation) {
case 1: return “Top, left side (Horizontal / normal)”;
case 2: return “Top, right side (Mirror horizontal)”;
case 3: return “Bottom, right side (Rotate 180)”;
case 4: return “Bottom, left side (Mirror vertical)”;
case 5: return “Left side, top (Mirror horizontal and rotate 270 CW)”;
case 6: return “Right side, top (Rotate 90 CW)”;
case 7: return “Right side, bottom (Mirror horizontal and rotate 90 CW)”;
case 8: return “Left side, bottom (Rotate 270 CW)”;
default:
return String.valueOf(orientation);
}
}
从这个方法可以清楚看到各个返回值的意思,如此我们便可以根据实际的返回值来对图像进行旋转或者是镜像处理了。
下面给出代码用以旋转图片,其他的关于图片的镜像等处理读者可以依此类推:
String mPath = “D:\XXX.JPG”;
File img = new File(mPath);
BufferedImage old_img = (BufferedImage)ImageIO.read(img);
int w = old_img.getWidth();
int h = old_img.getHeight();
BufferedImage new_img = new BufferedImage(h,w,BufferedImage.TYPE_INT_BGR);
Graphics2D g2d =new_img.createGraphics();
AffineTransform origXform = g2d.getTransform();
AffineTransform newXform = (AffineTransform)(origXform.clone());
// center of rotation is center of the panel
double xRot = w/2.0;
newXform.rotate(Math.toRadians(270.0), xRot, xRot); //旋转270度
g2d.setTransform(newXform);
// draw image centered in panel
g2d.drawImage(old_img, 0, 0, null);
aphics();
AffineTransform origXform = g2d.getTransform();
AffineTransform newXform = (AffineTransform)(origXform.clone());
// center of rotation is center of the panel
double xRot = w/2.0;
newXform.rotate(Math.toRadians(270.0), xRot, xRot); //旋转270度
g2d.setTransform(newXform);
// draw image centered in panel
g2d.drawImage(old_img, 0, 0, null);