Android图像resize和保存EXIF数据(方向,旋转等)

如果您的Android应用程序使用设备相机拍摄照片然后resize(这对减小上传大小非常常见),但是您可能没有意识到此大小调整操作会剥离 exif元数据。

这可能会导致问题,特别是如果有问题的设备依靠“方向”标签来正确显示图像。

不同的Android设备以不同的方式处理相机/图像旋转 – 我可信的“Nexus One”似乎总是在拍摄后立即旋转图像,所以文件的原始内容在观看时总是“直立的”。 然而,其他设备(尤其是我testing的三星手机),不要旋转图像文件的内容 – 而是设置exif“方向”标签。 每当稍后显示图像时,相关的图像代码应检测到方向“标签”的存在并适当地旋转图像。 但是,如果您对图像进行了任何位图处理并将其保存到新文件,则所有exif数据都将丢失。

除了方向数据,您还可能会失去其他有价值的元数据,如make / model等。

这使我困惑了几个星期(图像显示在手机画廊,直到后来到我的服务器方向不正确,没有明显的元数据直立。 我在这里添加这个自问题来帮助别人。 这篇博文很有帮助:

Android re-size image without loosing EXIF information

正如其他人所指出的,您必须将原始图像中的EXIF数据复制到最终resize的图像。 桑塞兰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方向标签是让每个程序正确显示图像的唯一方法。

[自我回答]

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

对于懒惰的,这是一个可重用的函数:

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