为了账号安全,请及时绑定邮箱和手机立即绑定

JAVA获取图片的元数据信息

标签:
Java
    我给大家分享的是我实际运行的效果,希望能够给想处理图片元数据的码友正确的引导。
    首先,我介绍一下元数据EXIF的概念,EXIF是 Exchangeable Image File的缩写,这是一种专门为数码相机照片设定的格式。这种格式可以用来记录数字照片的属性信息,例如相机的品牌及型号、相片的拍摄时间、拍摄时所设置的光圈大小、快门速度、ISO等等信息。除此之外它还能够记录拍摄数据,以及照片格式化方式等。

    其次我简单介绍一些jar里面的图片元数据参数(代码注释里面也很详细):
Image Description 图像描述、来源. 指生成图像的工具
Artist 作者 有些相机可以输入使用者的名字
Make 生产者 指产品生产厂家
Model 型号 指设备型号
Orientation方向 有的相机支持,有的不支持
XResolution/YResolution X/Y方向分辨率 本栏目已有专门条目解释此问题。
ResolutionUnit分辨率单位 一般为PPI
Software软件 显示固件Firmware版本
DateTime日期和时间
YCbCrPositioning 色相定位
ExifOffsetExif信息位置,定义Exif在信息在文件中的写入,有些软件不显示。
ExposureTime 曝光时间 即快门速度
FNumber光圈系数
ExposureProgram曝光程序 指程序式自动曝光的设置,各相机不同,可能是Sutter Priority(快门优先)、Aperture Priority(快门优先)等等。
ISO speed ratings感光度
ExifVersionExif版本
DateTimeOriginal创建时间
DateTimeDigitized数字化时间
ComponentsConfiguration图像构造(多指色彩组合方案)
CompressedBitsPerPixel(BPP)压缩时每像素色彩位 指压缩程度
ExposureBiasValue曝光补偿。
MaxApertureValue最大光圈
MeteringMode测光方式, 平均式测光、中央重点测光、点测光等。
Lightsource光源 指白平衡设置
Flash是否使用闪光灯。
FocalLength焦距,一般显示镜头物理焦距,有些软件可以定义一个系数,从而显示相当于35mm相机的焦距 MakerNote(User Comment)作者标记、说明、记录
FlashPixVersionFlashPix版本 (个别机型支持)
ColorSpace色域、色彩空间
ExifImageWidth(Pixel X Dimension)图像宽度 指横向像素数
ExifImageLength(Pixel Y Dimension)图像高度 指纵向像素数
Interoperability IFD通用性扩展项定义指针 和TIFF文件相关,具体含义不详
FileSource源文件 Compression压缩比。

详细的图片EXIF2.1标准参考网址:[https://tuchong.com/photo/6761525/exif/]

最后就是代码实现,我觉得没有什么过的的废话,直接上代码可以更好的思考:
代码所依赖的jar可以通过maven进行获取:

<dependency>  
    <groupId>com.drewnoakes</groupId>  
    <artifactId>metadata-extractor</artifactId>  
    <version>2.8.1</version>  
</dependency>  
java代码如下:
package image;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.drew.imaging.ImageMetadataReader;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.Tag;
import com.drew.metadata.exif.ExifIFD0Directory;
import com.drew.metadata.exif.ExifSubIFDDirectory;

public class metadatatest {
    /**
     * 注: Image Description 图像描述、来源. 指生成图像的工具
            Artist 作者 有些相机可以输入使用者的名字
            Make 生产者 指产品生产厂家
            Model 型号 指设备型号
            Orientation方向 有的相机支持,有的不支持
            XResolution/YResolution X/Y方向分辨率 本栏目已有专门条目解释此问题。
            ResolutionUnit分辨率单位 一般为PPI
            Software软件 显示固件Firmware版本
            DateTime日期和时间
            YCbCrPositioning 色相定位
            ExifOffsetExif信息位置,定义Exif在信息在文件中的写入,有些软件不显示。
            ExposureTime 曝光时间 即快门速度
            FNumber光圈系数
            ExposureProgram曝光程序 指程序式自动曝光的设置,各相机不同,可能是Sutter Priority(快门优先)、Aperture Priority(快门优先)等等。
            ISO speed ratings感光度
            ExifVersionExif版本
            DateTimeOriginal创建时间
            DateTimeDigitized数字化时间
            ComponentsConfiguration图像构造(多指色彩组合方案)
            CompressedBitsPerPixel(BPP)压缩时每像素色彩位 指压缩程度
            ExposureBiasValue曝光补偿。
            MaxApertureValue最大光圈
            MeteringMode测光方式, 平均式测光、中央重点测光、点测光等。
            Lightsource光源 指白平衡设置
            Flash是否使用闪光灯。
            FocalLength焦距,一般显示镜头物理焦距,有些软件可以定义一个系数,从而显示相当于35mm相机的焦距 MakerNote(User Comment)作者标记、说明、记录
            FlashPixVersionFlashPix版本 (个别机型支持)
            ColorSpace色域、色彩空间
            ExifImageWidth(Pixel X Dimension)图像宽度 指横向像素数
            ExifImageLength(Pixel Y Dimension)图像高度 指纵向像素数
            Interoperability IFD通用性扩展项定义指针 和TIFF文件相关,具体含义不详
            FileSource源文件 Compression压缩比。
     *
     * @作者: 张晓东
     * @创建日期: 2016年4月12日
     *
     * @param args
     * @throws Exception
     */

    public static void main(String[] args) throws Exception {
//      String path = "C:\\Users\\张晓东\\Desktop\\P1000702.JPG";
        String path = "C:\\Users\\张晓东\\Desktop\\IMG_20160404_170752.jpg";
//      String path = "C:\\Users\\张晓东\\Pictures\\1600FG100_048.jpg";
//      String path = "C:\\Users\\张晓东\\Desktop\\成品库-图片库2.jpg";
//      String path = "C:\\Users\\张晓东\\Desktop\\QQ截图20160414145054.png";
//      String path = "C:\\Users\\张晓东\\Desktop\\QQ截图20160414145212.bmp";
//      String path = "C:\\Users\\张晓东\\Pictures\\二.gif";
        getInfo(path);
    }

    public static void getInfo(String path){
        File imageFile = new File(path);
        try{

        Metadata metadata = ImageMetadataReader.readMetadata(imageFile);//ImageMetadataReader
        for (Directory directory : metadata.getDirectories()) {
            if(directory == null){
                continue;
            }
            for (Tag tag : directory.getTags()) {  
                String tagName = tag.getTagName(); // 标签名
                String desc = tag.getDescription(); // 标签信息
                String directName = tag.getDirectoryName();//文档名字
                if (tagName.equals("GPS Latitude")) {
                    System.err.println("纬度 : " + desc);
                    // System.err.println("纬度(度分秒格式) : "+pointToLatlong(desc));
                } else if (tagName.equals("GPS Longitude")) {
                    System.err.println("经度: " + desc);
                    // System.err.println("经度(度分秒格式): "+pointToLatlong(desc));
                } else if (tagName.equals("GPS Altitude")) {
                    System.err.println("海拔: " + desc);
                } else if (tagName.equals("Date/Time Original")){
                        SimpleDateFormat yyyymmddhhmmss = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
                        Date date = yyyymmddhhmmss.parse(desc);
                        SimpleDateFormat newFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        System.out.println("拍照时间: " + newFormat.format(date));
                } else if (tagName.equals("Date/Time")){
                    SimpleDateFormat yyyymmddhhmmss = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
                    Date date = yyyymmddhhmmss.parse(desc);
                    SimpleDateFormat newFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    System.out.println("创建时间: " + newFormat.format(date));
                } else if (tagName.equals("Image Width")){
                    System.err.println("宽: " + Integer.parseInt(desc.replaceAll("[^0-9]", "").trim()));
                } else if (tagName.equals("Image Height")){
                    System.err.println("高: " + Integer.parseInt(desc.replaceAll("[^0-9]", "").trim()));
                } else if (tagName.equals("X Resolution")){
                    System.err.println("水平分辨率: " + Integer.parseInt(desc.replaceAll("[^0-9]", "").trim()));
                } else if (tagName.equals("Y Resolution")){
                    System.err.println("垂直分辨率: " + Integer.parseInt(desc.replaceAll("[^0-9]", "").trim()));
                }
            }
            if(directory.containsTag(ExifSubIFDDirectory.TAG_FNUMBER)){
                //光圈F值=镜头的焦距/镜头光圈的直径
                System.out.println("光圈值:"+directory.getDescription(ExifSubIFDDirectory.TAG_FNUMBER));
            }
            if(directory.containsTag(ExifSubIFDDirectory.TAG_EXPOSURE_TIME)){
                System.out.println("曝光时间: " + directory.getString(ExifSubIFDDirectory.TAG_EXPOSURE_TIME)+ "秒");
            }
            if(directory.containsTag(ExifSubIFDDirectory.TAG_ISO_EQUIVALENT)){
                System.out.println("ISO速度: " + directory.getString(ExifSubIFDDirectory.TAG_ISO_EQUIVALENT));
            }
            if(directory.containsTag(ExifSubIFDDirectory.TAG_FOCAL_LENGTH)){
                System.out.println("焦距: " + directory.getString(ExifSubIFDDirectory.TAG_FOCAL_LENGTH)+ "毫米");
            }
            if(directory.containsTag(ExifSubIFDDirectory.TAG_MAX_APERTURE)){
                System.out.println("最大光圈:" + directory.getDouble(ExifSubIFDDirectory.TAG_MAX_APERTURE));
            }
            if(directory.containsTag(ExifSubIFDDirectory.TAG_EXIF_IMAGE_WIDTH)){
                System.out.println("宽: " + directory.getString(ExifIFD0Directory.TAG_EXIF_IMAGE_WIDTH));//ExifIFD0Directory
            }
            if(directory.containsTag(ExifSubIFDDirectory.TAG_EXIF_IMAGE_HEIGHT)){
                System.out.println("高: " + directory.getString(ExifSubIFDDirectory.TAG_EXIF_IMAGE_HEIGHT));
            }
            if(directory.containsTag(ExifSubIFDDirectory.TAG_MAKE)){
                System.out.println("照相机制造商: " + directory.getString(ExifSubIFDDirectory.TAG_MAKE));
            }
            if(directory.containsTag(ExifSubIFDDirectory.TAG_MODEL)){
                System.out.println("照相机型号: " + directory.getString(ExifSubIFDDirectory.TAG_MODEL));
            }
            if(directory.containsTag(ExifSubIFDDirectory.TAG_X_RESOLUTION)){
                System.out.println("水平分辨率(X方向分辨率): " + directory.getString(ExifSubIFDDirectory.TAG_X_RESOLUTION));
            }
            if(directory.containsTag(ExifSubIFDDirectory.TAG_Y_RESOLUTION)){
                System.out.println("垂直分辨率(Y方向分辨率): " + directory.getString(ExifSubIFDDirectory.TAG_Y_RESOLUTION));
            }
            //其他参数测试开始
            if(directory.containsTag(ExifSubIFDDirectory.TAG_SOFTWARE)){
                //Software软件 显示固件Firmware版本
                System.out.println("显示固件Firmware版本(图片详细信息的程序名称):" + directory.getString(ExifSubIFDDirectory.TAG_SOFTWARE));
            }
            if(directory.containsTag(ExifSubIFDDirectory.TAG_35MM_FILM_EQUIV_FOCAL_LENGTH)){
                System.out.println("35mm焦距:" + directory.getString(ExifSubIFDDirectory.TAG_35MM_FILM_EQUIV_FOCAL_LENGTH));
            }
            if(directory.containsTag(ExifSubIFDDirectory.TAG_APERTURE)){
                System.out.println("孔径(图片分辨率单位):" + directory.getString(ExifSubIFDDirectory.TAG_APERTURE));
            } else {
//              System.out.println("孔径");
            }
            if(directory.containsTag(ExifSubIFDDirectory.TAG_APPLICATION_NOTES)){
                //一般无
                System.out.println("应用程序记录:" + directory.getString(ExifSubIFDDirectory.TAG_APPLICATION_NOTES));
            }
            if(directory.containsTag(ExifSubIFDDirectory.TAG_ARTIST)){
                //作者
                System.out.println("作者:" + directory.getString(ExifSubIFDDirectory.TAG_ARTIST));
            }
            if(directory.containsTag(ExifSubIFDDirectory.TAG_BODY_SERIAL_NUMBER)){
                System.out.println("TAG_BODY_SERIAL_NUMBER:" + directory.getString(ExifSubIFDDirectory.TAG_BODY_SERIAL_NUMBER));
            }
            if(directory.containsTag(ExifSubIFDDirectory.TAG_METERING_MODE)){
                //MeteringMode测光方式, 平均式测光、中央重点测光、点测光等
                System.out.println("点测光值:" + directory.getString(ExifSubIFDDirectory.TAG_METERING_MODE));
            }
            if(directory.containsTag(ExifSubIFDDirectory.TAG_RESOLUTION_UNIT)){
                //XResolution/YResolution X/Y方向分辨率
                System.out.println("分辨率单位:" + directory.getString(ExifSubIFDDirectory.TAG_RESOLUTION_UNIT));
            }
            if(directory.containsTag(ExifSubIFDDirectory.TAG_EXPOSURE_BIAS)){
                System.out.println("曝光补偿:" + directory.getDouble(ExifSubIFDDirectory.TAG_EXPOSURE_BIAS));
            }
            if(directory.containsTag(ExifSubIFDDirectory.TAG_COLOR_SPACE)){
                System.out.println("色域、色彩空间:" + directory.getString(ExifSubIFDDirectory.TAG_COLOR_SPACE));
            }
            if(directory.containsTag(ExifSubIFDDirectory.TAG_YCBCR_COEFFICIENTS)){
                System.out.println("色相系数:" + directory.getString(ExifSubIFDDirectory.TAG_YCBCR_COEFFICIENTS));
            }
            if(directory.containsTag(ExifSubIFDDirectory.TAG_YCBCR_POSITIONING)){
                System.out.println("色相定位:" + directory.getString(ExifSubIFDDirectory.TAG_YCBCR_POSITIONING));
            }
            if(directory.containsTag(ExifSubIFDDirectory.TAG_YCBCR_SUBSAMPLING)){
                System.out.println("色相抽样:" + directory.getString(ExifSubIFDDirectory.TAG_YCBCR_SUBSAMPLING));
            }
            if(directory.containsTag(ExifSubIFDDirectory.TAG_EXIF_VERSION)){
                System.out.println("exif版本号:" + directory.getString(ExifSubIFDDirectory.TAG_EXIF_VERSION));
            }
        }  
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 经纬度格式 转换为 度分秒格式 ,如果需要的话可以调用该方法进行转换
     * 
     * @param point
     *            坐标点
     * @return
     */
    public static String pointToLatlong(String point) {
        Double du = Double.parseDouble(point.substring(0, point.indexOf("°")).trim());
        Double fen = Double.parseDouble(point.substring(point.indexOf("°") + 1, point.indexOf("‘")).trim());
        Double miao = Double.parseDouble(point.substring(point.indexOf("‘") + 1, point.indexOf("\"")).trim());
        Double duStr = du + fen / 60 + miao / 60 / 60;
        return duStr.toString();
    }

}

废不多说,以上就是自己学习的代码思路,我要说以下几点注意:
1.依赖的ja我用的是metadata-extractor-2.9.0.jar是直接下载的jar,上面的maven引用是2.8.1的,你用的maven仓库不一样可能版本也不一样,不过大部分还是都有的。
2.如果获取的更准确的元数据信息,可以通过标签名字(tag.getTagName(); // 标签名)的方式找到,这样获取的一般都是准确的。
3.当你循环打印metadata.getDirectories()元数据节点的时候,会发现一下括号包括的[JPEG]、[Exif Thumbnail]、[Exif IFD0]可以自己循环一下打印看看。这些节点相当于元数据的分类,里面包含了标签。如下代码:

 public static void metadataExtractor(){  
        File jpegFile = new File("37.jpg");  
        try {  
            Metadata metadata = ImageMetadataReader.readMetadata(jpegFile);  
            for (Directory directory : metadata.getDirectories()) {  
                for (Tag tag : directory.getTags()) {  
                    System.out.println(tag);  
                }  
            }  
        } catch (ImageProcessingException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
    以上是我的心得,可能总结的不够全面,亦获取有漏洞,希望广大码友要指教。
点击查看更多内容
9人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消