關於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封裝類的代碼。

 

最后,展示一下具體應用於網站的實際效果:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM