zoukankan      html  css  js  c++  java
  • 关于Java 如何采用 metadata-extractor 读取数码相机 Exif 数据信息的代码

    最近做了一个关于图片blog的系统,当中涉及到大量的图片上传与下载,这也是blog工程无法避免的。

    对于上传图片来说,有很多开源java代码可供选择,今天这里要说的是一个比较特殊,需求中很少遇到的情况,

    那就是,对于图片中,如果存在元数据(Exif)信息时,需要怎么读取?

    什么是Exif?

    它是一组,专门为数码相机照片设定的数据存储信息(包括拍摄日期、数码相机功能信息等数据),可附加于JPEG、TIFF、RIFF等文件之中,

    它是由 日本电子工业发展协会在1996年制定的,抛却民族情怀,日本人真的有很多值得学习的方面。

    我们该怎么解决?

    有了这个需求,那么现在就需要为客户解决这个问题了。既然我们已经知道Exif是什么东西了,那么自然就会有针对它的办法出现。

    之前,查找了好些关于这个方面的资料,很多人说出了很多办法,更有甚者说可以结合C++进行处理的方式,这个就有点过了。

    个人觉得,解决问题还是要本着实际环境范围内来思考,要是天马行空的想象一通则毫无意义,你干脆说把人家日本工业协会的接口封装打包给你调用算了,这根本不可能的事情!

    但好在,坚信办法永远要比困难多的强大信心,发现,在这个美丽多彩的java世界里,早已经有巨人为我们提供了更优秀的解决办法。

    最后,我决定还是站在巨人的肩膀上一路向前吧!毕竟个人的精力是有限的!

    到此,解决方向找到了,那就是采用 metadata-extractor 完全可以进行处理Exif数据信息。

    砍柴必先利其器,所以准备工具如下:

    Java包:metadata-extractor-2.13.0.jar

    Eclipse:Eclipse IDE for Enterprise Java Developers. Version: 2020-03 (4.15.0)

    Maven:apache-maven-3.6.3

    个人比较喜欢采用Maven来构建项目,所以毫无疑问,首先来配置一段pom.xml信息。

    <!-- https://mvnrepository.com/artifact/com.drewnoakes/metadata-extractor -->
    <dependency>
        <groupId>com.drewnoakes</groupId>
        <artifactId>metadata-extractor</artifactId>
        <version>2.13.0</version>
    </dependency>

    构建完之后,废话就不多说了,直接上核心代码,分享成果:

    package music.tools;
    
    import java.io.File;
    import java.io.InputStream;
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    
    import com.drew.imaging.ImageMetadataReader;
    import com.drew.metadata.Directory;
    import com.drew.metadata.Metadata;
    import com.drew.metadata.Tag;
    
    /**
     * 图片Exif标签帮助类
     * 
     * @author Mcqueen Xing (邢志)
     * @date 2016年5月12日上午9:20:26
     *
     */
    public class ExifHelper {
        Metadata metadata = null;
        public ExifHelper(File f) throws Exception {
            metadata = ImageMetadataReader.readMetadata(f);
        }
    
        public ExifHelper(String path) throws Exception {
            File f = new File(path);
            metadata = ImageMetadataReader.readMetadata(f);
        }
    
        public ExifHelper(InputStream is) throws Exception {
            metadata = ImageMetadataReader.readMetadata(is);
        }
    
        /**
         * 获取Exif信息文件夹
         * 
         * @author Mcqueen Xing (邢志)
         * @date 2016年5月12日 上午10:10:57
         * @return
         */
        private Iterable<Directory> getDirectoryList() {
            Iterable<Directory> iterable = metadata.getDirectories();
            return iterable;
        }
    
        private List<Directory> getDir() {
            List<Directory> lstDir = new ArrayList<Directory>();
            for (Iterator<Directory> iter = getDirectoryList().iterator(); iter
                    .hasNext();) {
                Directory dr = iter.next();
                lstDir.add(dr);
            }
            return lstDir;
        }
    
        /**
         * 获取Exif Directory 对象下的 Tag 集合
         * 
         * @author Mcqueen Xing (邢志)
         * @date 2016年5月12日 上午10:29:18
         * @return
         */
        private List<Collection<Tag>> getTars() {
            List<Collection<Tag>> lsttag = new ArrayList<Collection<Tag>>();
            for (Directory d : getDir()) {
                lsttag.add(d.getTags());
            }
            return lsttag;
        }
    
        /**
         * 获取不同的 Exif 分类文件夹名称
         * 
         * @author Mcqueen Xing (邢志)
         * @date 2016年5月12日 上午10:29:57
         * @param type
         * @return
         */
        private String getExifDirectoryName(int type) {
            String directoryName = "File";
            switch (type) {
            case 1:
                directoryName = "Exif SubIFD";
                break;
            case 2:
                directoryName = "Exif IFD0";
                break;
            case 3:
                directoryName = "JFIF";
                break;
            case 4:
                directoryName = "JPEG";
                break;
            case 5:
                directoryName = "File";
            default:
                break;
            }
            return directoryName;
        }
    
        /**
         * 指定键获取 Exif 元数据的属性值.
         * 
         * @author Mcqueen Xing (邢志)
         * @date 2016年5月12日 上午10:21:01
         * @param tagKey
         *            Tag 键名称
         * @param type
         *            获取类型:1.Exif SubIFD; 2.Exif IFD0; 3.JFIF; 4.JPEG; 5.File;
         * @return
         */
        public String getTagByKey(String tagKey, int type) {
            String tagValue = "";
            if (type > 5)
                return tagValue;
            List<Collection<Tag>> lstTag = getTars();
            boolean sgin = true;
            for (Collection<Tag> tagColl : lstTag) {
                if (!sgin)
                    break;
                for (Tag tag : tagColl) {
                    if (tag.getTagName().equals(tagKey)
                            && tag.getDirectoryName().equals(
                                    getExifDirectoryName(type))) {
                        tagValue = tag.getDescription();
                        sgin = false;
                        break;
                    }
                }
            }
            return tagValue;
        }
    
        /**
         * 获取图片的所有 Exif 信息.
         * 
         * @author Mcqueen Xing (邢志)
         * @date 2016年5月12日 上午10:21:01
         * @param tagKey
         *            Tag 键名称
         * @param type
         *            获取类型:1.Exif SubIFD; 2.Exif IFD0; 3.JFIF; 4.JPEG; 5.File;
         * @return
         */
        public HashMap<String, String> getAllTags() {
            HashMap<String, String> map = new HashMap<String, String>();
            List<Collection<Tag>> lstTag = getTars();
            for (Collection<Tag> tagColl : lstTag) {
                for (Tag tag : tagColl) {
                    map.put(tag.getTagName(), tag.getDescription());
                    // System.out.println(tag.getTagName() + ":" +
                    // tag.getDescription() + "[" + tag.getDirectoryName() + "]");
                }
            }
            return map;
        }
    
        /**
         * 获取 Exif 日期元数据.
         * 
         * @author Mcqueen Xing (邢志)
         * @date 2016年5月12日 上午11:36:20
         * @return
         */
        public String getExifDateTime(boolean ishash) {
            String currentTime = "";
            if (!ishash) {
                currentTime = getTagByKey("Date/Time Original", 1);
                if (currentTime != "") {
                    currentTime = currentTime.split(" ")[0].replace(':', '-') + " "
                            + currentTime.split(" ")[1];
                } else {
                    currentTime = getTagByKey("File Modified Date", 5);
                    if (currentTime.indexOf("CST") > -1
                            || currentTime.indexOf("GMT") > -1) {
                        currentTime = DateHelper
                                .TransferEnglishDateTime(currentTime);
                    } else {
                        currentTime = DateHelper.FormatDateToString(new Date(), 1);
                    }
                }
            } else {
                currentTime = getExifDateTimeByKeyFromHashMap("Date/Time Original");
                if (currentTime != null && !currentTime.equals("")) {
                    // Tue Jun 22 09:28:12 CST 2010
                    if (currentTime.indexOf("CST") >= 0
                            || currentTime.indexOf("GMT") >= 0) {
                        currentTime = DateHelper
                                .TransferEnglishDateTime(currentTime);
                    } else {
                        currentTime = currentTime.split(" ")[0].replace(':', '-')
                                + " " + currentTime.split(" ")[1];
                    }
                } else {
                    currentTime = getExifDateTimeByKeyFromHashMap("File Modified Date");
    
                    if ((currentTime != null)) {
                        if (currentTime.indexOf("CST") > -1
                                || currentTime.indexOf("GMT") > -1)
                            currentTime = DateHelper
                                    .TransferEnglishDateTime(currentTime);
                    } else {
                        currentTime = DateHelper.FormatDateToString(new Date(), 1);
                    }
                }
            }
            return currentTime;
        }
    
        /**
         * 获取 Exif 日期元数据.通过属性名称.
         * 
         * @author Mcqueen Xing (邢志)
         * @date 2016年5月12日 上午11:36:20
         * @return
         */
        /*
         * public String getExifDateTime(){ return ""; }
         */
        private String getExifDateTimeByKeyFromHashMap(String key) {
            HashMap<String, String> hash = getAllTags();
            return hash.get(key);
        }
    
        /**
         * 获取 Exif 相机制造商信息
         * 
         * @author Mcqueen Xing (邢志)
         * @date 2016年5月12日 上午11:47:03
         * @return
         */
        public String getExifMake() {
            String make = "";
            make = getTagByKey("Make", 2);
            return make;
        }
    
        /**
         * 获取 Exif 相机型号信息
         * 
         * @author Mcqueen Xing (邢志)
         * @date 2016年5月12日 上午11:47:03
         * @return
         */
        public String getExifModel() {
            String model = "";
            model = getTagByKey("Model", 2);
            return model;
        }
    }

    使用方法,如图:

    为了避免Copy行为的懒惰造成思维生疏,此处采用截图展示,如何引用Exif封装类的代码。

    最后,展示一下具体应用于网站的实际效果:

  • 相关阅读:
    RestTemplate的异常:Not enough variables available to expand
    WebApplicationContext类的作用
    select动态绑定vue.js
    spring的 @Scheduled的cron表达式
    Spring使用webjar
    ThreadLocal基本原理及运用
    mybatis choose标签的使用
    @RequestBody和@RequestParam区别
    js遍历 for-of
    MySql 模糊查询
  • 原文地址:https://www.cnblogs.com/mcqueen/p/12792071.html
Copyright © 2011-2022 走看看