2012-11-28 45 views
38

如果Android應用使用設備的相機拍照,然後調整它的大小(這是很常見的,以減少上傳大小),你可能會不知道這調整操作的EXIF元數據。Android的圖像大小調整和保留EXIF數據(取向,旋轉等)

這可能會導致問題,尤其是如果有問題的設備依賴於「定位」標籤正確顯示圖像直立。

不同的Android設備不同的方式處理相機/圖像旋轉 - 我信賴的醇」的Nexus One似乎永遠旋轉圖像後立即拍攝,因此該文件的本地內容總是‘看時直立’。然而,其他設備(尤其是三星手機在我的測試),做旋轉圖像文件的內容 - 相反,他們設置了EXIF「定位」的標籤。每當稍後顯示圖像時,相關圖像代碼應檢測到方向'標記'的存在並適當旋轉圖像。但是,如果您對圖像執行了任何位圖處理並將其保存到新文件,則所有exif數據都將丟失。

除了定位數據,你也可能會失去其他有價值的元數據,例如品牌/型號等

這讓我感到困惑的幾個星期(在手機圖片庫中顯示圖像時出現直立,但隨後就到達我的服務器方向不對,沒有明顯的元數據)。我在這裏添加這個自問題來幫助別人。本博客文章是非常有益的:

http://vikaskanani.wordpress.com/2011/07/17/android-re-size-image-without-loosing-exif-information/

回答

15

正如其他人所指出的,你必須從原始圖像複製的EXIF數據到最終調整圖像。 Sanselan Android庫通常最適合這一點。根據Android操作系統版本的不同,ExifInterface有時會破壞EXIF數據。另外,ExifInterface還處理有限數量的Exif標籤 - 即只有它「知道」的標籤。另一方面Sanselan將保留所有EXIF標籤和標記註釋。

這裏是一個博客帖子裏介紹如何使用Sanselan用於複製圖像數據: http://bricolsoftconsulting.com/copying-exif-metadata-using-sanselan/

順便說一句,在Android上我也傾向於旋轉圖像並刪除定位EXIF標籤。例如,在搭載Android 4.03的Nexus S上,相機在EXIF元數據中設置了方向標籤,但webview忽略了該信息並錯誤地顯示了圖像。令人遺憾的是,旋轉實際圖像數據並刪除EXIF方向標籤是讓每個程序正確顯示圖像的唯一方法。

+0

謝謝西奧,我很欣賞這個答案並已接受它。你有鏈接瞭解更多關於這個的信息「根據Android操作系統版本的不同,ExifInterface有時會破壞EXIF數據。」 –

+0

這是基於我的經驗,我不是第一個發現ExifInterface是越野車的人[1]。根據我在未來幾天的時間,我可能會彙總一些說明性的案例並回報。 [1] http://mail-archives.apache.org/mod_mbox/commons-issues/201106.mbox/%[email protected]e.org%3E – Theo

+0

@Theo i'我測試了你的代碼,它似乎複製了一些設備和圖像的大部分/全部屬性。不能很好複製的屬性示例:ISOSpeedRatings,FocalLength,FNumber。你能解釋一下它怎麼可能?我已經用Android 4.4.2在nexus 4設備上測試過它,並比較了在原始文件和新文件上創建的ExifInterface。 –

33

[自答案]

AFAICT,有沒有機制來自動甚至堅持的元數據快照無論是存在的,轉讓散裝。

相反,它似乎你必須明確地檢查特定的屬性和自己將它們複製到使用ExifInterface新的圖像文件。

http://developer.android.com/reference/android/media/ExifInterface.html

因此,像:

ExifInterface oldExif = new ExifInterface(oldImagePath); 
String exifOrientation = oldExif.getAttribute(ExifInterface.TAG_ORIENTATION); 

if (exifOrientation != null) { 
    ExifInterface newExif = new ExifInterface(imagePath); 
    newExif.setAttribute(ExifInterface.TAG_ORIENTATION, exifOrientation); 
    newExif.saveAttributes(); 
} 
+0

這完美地工作。謝謝! – Mauker

22

對於懶惰的,這裏有一個可重複使用的功能:

public static void copyExif(String oldPath, String newPath) throws IOException 
{ 
    ExifInterface oldExif = new ExifInterface(oldPath); 

    String[] attributes = new String[] 
    { 
      ExifInterface.TAG_APERTURE, 
      ExifInterface.TAG_DATETIME, 
      ExifInterface.TAG_DATETIME_DIGITIZED, 
      ExifInterface.TAG_EXPOSURE_TIME, 
      ExifInterface.TAG_FLASH, 
      ExifInterface.TAG_FOCAL_LENGTH, 
      ExifInterface.TAG_GPS_ALTITUDE, 
      ExifInterface.TAG_GPS_ALTITUDE_REF, 
      ExifInterface.TAG_GPS_DATESTAMP, 
      ExifInterface.TAG_GPS_LATITUDE, 
      ExifInterface.TAG_GPS_LATITUDE_REF, 
      ExifInterface.TAG_GPS_LONGITUDE, 
      ExifInterface.TAG_GPS_LONGITUDE_REF, 
      ExifInterface.TAG_GPS_PROCESSING_METHOD, 
      ExifInterface.TAG_GPS_TIMESTAMP, 
      ExifInterface.TAG_IMAGE_LENGTH, 
      ExifInterface.TAG_IMAGE_WIDTH, 
      ExifInterface.TAG_ISO, 
      ExifInterface.TAG_MAKE, 
      ExifInterface.TAG_MODEL, 
      ExifInterface.TAG_ORIENTATION, 
      ExifInterface.TAG_SUBSEC_TIME, 
      ExifInterface.TAG_SUBSEC_TIME_DIG, 
      ExifInterface.TAG_SUBSEC_TIME_ORIG, 
      ExifInterface.TAG_WHITE_BALANCE 
    }; 

    ExifInterface newExif = new ExifInterface(newPath); 
    for (int i = 0; i < attributes.length; i++) 
    { 
     String value = oldExif.getAttribute(attributes[i]); 
     if (value != null) 
      newExif.setAttribute(attributes[i], value); 
    } 
    newExif.saveAttributes(); 
} 
+4

如果調整大小,請記得更新或不要複製TAG_IMAGE_LENGTH和TAG_IMAGE_WIDTH –