2012-11-28 43 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 –