关于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封装类的代码。

 

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

 

posted @ 2020-04-28 09:45  迦南邪恋  阅读(1401)  评论(0编辑  收藏  举报