编程知识 cdmana.com

Android中讀取圖片EXIF元數據之metadata-extractor的使用

*/

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);

// Reset to Original

g2d.setTransform(origXform);

//寫到新的文件

FileOutputStream out = new FileOutputStream(“D:\XXX2.jpg”);

try{

ImageIO.write(new_img, “JPG”, out);

}finally{

out.close();

}

注:利用上面的代碼旋轉照片後,原有照片包含的EXIF信息就不存在了。關於該問題需要在照片旋轉之前先把EXIF信息讀出,然後再在旋轉後寫入新的照片中,可以使用 MediaUtil 包來寫EXIF信息到圖片文件中,關於這個包的使用可參考最後的鏈接。

照片的鏡面翻轉可以直接利用Graphic2D 的 drawImage 方法來實現:

public abstract boolean drawImage(Image img,

int dx1,int dy1,

int dx2,int dy2,

int sx1,int sy1,

int sx2,int sy2,

ImageObserver observer);

三、補充說明

最後

這裏我特地整理了一份《Android開發核心知識點筆記》,裏面就包含了自定義View相關的內容

如果你有需要的話,可以私信我【進階】發給你

Android中讀取圖片EXIF元數據之metadata-extractor的使用_Android

除了這份筆記,還給大家分享?Android學習PDF+架構視頻+面試文檔+源碼筆記,高級架構技術進階腦圖、Android開發面試專題資料,高級進階架構資料這幾塊的內容。非常適合近期有面試和想在技術道路上繼續精進的朋友。

如果你有需要的話, 可以點擊我的GitHub免費獲取!

Android中讀取圖片EXIF元數據之metadata-extractor的使用_移動開發_02

分享上面這些資源,希望可以幫助到大家提昇進階,如果你覺得還算有用的話,不妨把它們推薦給你的朋友~

喜歡本文的話,給我點個小贊、評論區留言或者轉發支持一下唄~

版权声明
本文为[mb61c1dbbb44788]所创,转载请带上原文链接,感谢
https://cdmana.com/2022/01/202201150207009094.html

Scroll to Top