简介:
Exif是一种图像文件格式,它的数据存储与JPEG格式是完全相同的。实际上Exif格式就是在JPEG格式头部插入了数码照片的信息,包括拍摄时的光圈、快门、白平衡、ISO、焦距、日期时间等各种和拍摄条件以及相机品牌、型号、色彩编码、拍摄时录制的声音以及GPS全球定位系统数据、缩略图等。你可以利用任何可以查看JPEG文件的看图软件浏览Exif格式的照片,但并不是所有的图形程序都能处理Exif信息。今天这篇文章就来讲讲Android中操作Exif。
段子:
老规矩,在节目开始之前,先来一个搞笑段子: 我:老板,来30斤肉。 老板:好嘞。 我:30斤这么多啊! 老板:来,我给您装上。 我:哦不用了,我就想看看30斤肉有多少,我想减肥。 老板:窝草,你别跑~
ExifInterface:
Android开发中,在对图片进行展示、编辑、发送等操作时经常会涉及Exif的操作,Android中操作Exif主要是通过ExifInterface,ExifInterface看上去是一个接口,其实是一个类,位于Android.media.ExifInterface的位置。进入ExifInterface类,发现方法很少,主要就是三个方面:读取、写入、缩略图。
一、读取:
Exif信息在文件头中是以二进制的形式存储的,存储的字段名称和字段值格式都是固定的。我测试的Android23(6.0)版本中,总共有26个Exif字段,其中TAG_SUBSECTIME被加上了@hide注解,也就是还剩25个,我写了个demo,获取这25个字段的值,看看都是什么样的格式。
Demo:这个demo会对25个字段作解释
ExifInterface exifInterface = new ExifInterface(filePath); | |
String orientation = exifInterface.getAttribute(ExifInterface.TAG_ORIENTATION); | |
String dateTime = exifInterface.getAttribute(ExifInterface.TAG_DATETIME); | |
String make = exifInterface.getAttribute(ExifInterface.TAG_MAKE); | |
String model = exifInterface.getAttribute(ExifInterface.TAG_MODEL); | |
String flash = exifInterface.getAttribute(ExifInterface.TAG_FLASH); | |
String imageLength = exifInterface.getAttribute(ExifInterface.TAG_IMAGE_LENGTH); | |
String imageWidth = exifInterface.getAttribute(ExifInterface.TAG_IMAGE_WIDTH); | |
String latitude = exifInterface.getAttribute(ExifInterface.TAG_GPS_LATITUDE); | |
String longitude = exifInterface.getAttribute(ExifInterface.TAG_GPS_LONGITUDE); | |
String latitudeRef = exifInterface.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF); | |
String longitudeRef = exifInterface.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF); | |
String exposureTime = exifInterface.getAttribute(ExifInterface.TAG_EXPOSURE_TIME); | |
String aperture = exifInterface.getAttribute(ExifInterface.TAG_APERTURE); | |
String isoSpeedRatings = exifInterface.getAttribute(ExifInterface.TAG_ISO); | |
String dateTimeDigitized = exifInterface.getAttribute(ExifInterface.TAG_DATETIME_DIGITIZED); | |
String subSecTime = exifInterface.getAttribute(ExifInterface.TAG_SUBSEC_TIME); | |
String subSecTimeOrig = exifInterface.getAttribute(ExifInterface.TAG_SUBSEC_TIME_ORIG); | |
String subSecTimeDig = exifInterface.getAttribute(ExifInterface.TAG_SUBSEC_TIME_DIG); | |
String altitude = exifInterface.getAttribute(ExifInterface.TAG_GPS_ALTITUDE); | |
String altitudeRef = exifInterface.getAttribute(ExifInterface.TAG_GPS_ALTITUDE_REF); | |
String gpsTimeStamp = exifInterface.getAttribute(ExifInterface.TAG_GPS_TIMESTAMP); | |
String gpsDateStamp = exifInterface.getAttribute(ExifInterface.TAG_GPS_DATESTAMP); | |
String whiteBalance = exifInterface.getAttribute(ExifInterface.TAG_WHITE_BALANCE); | |
String focalLength = exifInterface.getAttribute(ExifInterface.TAG_FOCAL_LENGTH); | |
String processingMethod = exifInterface.getAttribute(ExifInterface.TAG_GPS_PROCESSING_METHOD); | |
Log.e("TAG", "## orientation=" + orientation); | |
Log.e("TAG", "## dateTime=" + dateTime); | |
Log.e("TAG", "## make=" + make); | |
Log.e("TAG", "## model=" + model); | |
Log.e("TAG", "## flash=" + flash); | |
Log.e("TAG", "## imageLength=" + imageLength); | |
Log.e("TAG", "## imageWidth=" + imageWidth); | |
Log.e("TAG", "## latitude=" + latitude); | |
Log.e("TAG", "## longitude=" + longitude); | |
Log.e("TAG", "## latitudeRef=" + latitudeRef); | |
Log.e("TAG", "## longitudeRef=" + longitudeRef); | |
Log.e("TAG", "## exposureTime=" + exposureTime); | |
Log.e("TAG", "## aperture=" + aperture); | |
Log.e("TAG", "## isoSpeedRatings=" + isoSpeedRatings); | |
Log.e("TAG", "## dateTimeDigitized=" + dateTimeDigitized); | |
Log.e("TAG", "## subSecTime=" + subSecTime); | |
Log.e("TAG", "## subSecTimeOrig=" + subSecTimeOrig); | |
Log.e("TAG", "## subSecTimeDig=" + subSecTimeDig); | |
Log.e("TAG", "## altitude=" + altitude); | |
Log.e("TAG", "## altitudeRef=" + altitudeRef); | |
Log.e("TAG", "## gpsTimeStamp=" + gpsTimeStamp); | |
Log.e("TAG", "## gpsDateStamp=" + gpsDateStamp); | |
Log.e("TAG", "## whiteBalance=" + whiteBalance); | |
Log.e("TAG", "## focalLength=" + focalLength); | |
Log.e("TAG", "## processingMethod=" + processingMethod); |
打印结果如下:
E/TAG: ## orientation=0 | |
E/TAG: ## dateTime=2016:05:23 17:30:11 | |
E/TAG: ## make=Xiaomi | |
E/TAG: ## model=Mi-4c | |
E/TAG: ## flash=16 | |
E/TAG: ## imageLength=4160 | |
E/TAG: ## imageWidth=3120 | |
E/TAG: ## latitude=31/1,58/1,253560/10000 | |
E/TAG: ## longitude=118/1,44/1,491207/10000 | |
E/TAG: ## latitudeRef=N | |
E/TAG: ## longitudeRef=E | |
E/TAG: ## exposureTime=0.050 | |
E/TAG: ## aperture=2.0 | |
E/TAG: ## iso=636 | |
E/TAG: ## dateTimeDigitized=2016:05:23 17:30:11 | |
E/TAG: ## subSecTime=379693 | |
E/TAG: ## subSecTimeOrig=379693 | |
E/TAG: ## subSecTimeDig=379693 | |
E/TAG: ## altitude=0/1000 | |
E/TAG: ## altitudeRef=0 | |
E/TAG: ## gpsTimeStamp=9:30:8 | |
E/TAG: ## gpsDateStamp=2016:05:23 | |
E/TAG: ## whiteBalance=0 | |
E/TAG: ## focalLength=412/100 | |
E/TAG: ## processingMethod=NETWORK |
这25个字段分别是代表什么呢?
ExifInterface.TAG_ORIENTATION //旋转角度,整形表示,在ExifInterface中有常量对应表示 | |
ExifInterface.TAG_DATETIME //拍摄时间,取决于设备设置的时间 | |
ExifInterface.TAG_MAKE //设备品牌 | |
ExifInterface.TAG_MODEL //设备型号,整形表示,在ExifInterface中有常量对应表示 | |
ExifInterface.TAG_FLASH //闪光灯 | |
ExifInterface.TAG_IMAGE_LENGTH //图片高度 | |
ExifInterface.TAG_IMAGE_WIDTH //图片宽度 | |
ExifInterface.TAG_GPS_LATITUDE //纬度 | |
ExifInterface.TAG_GPS_LONGITUDE //经度 | |
ExifInterface.TAG_GPS_LATITUDE_REF //纬度名(N or S) | |
ExifInterface.TAG_GPS_LONGITUDE_REF //经度名(E or W) | |
ExifInterface.TAG_EXPOSURE_TIME //曝光时间 | |
ExifInterface.TAG_APERTURE //光圈值 | |
ExifInterface.TAG_ISO //ISO感光度 | |
ExifInterface.TAG_DATETIME_DIGITIZED //数字化时间 | |
ExifInterface.TAG_SUBSEC_TIME // | |
ExifInterface.TAG_SUBSEC_TIME_ORIG // | |
ExifInterface.TAG_SUBSEC_TIME_DIG // | |
ExifInterface.TAG_GPS_ALTITUDE //海拔高度 | |
ExifInterface.TAG_GPS_ALTITUDE_REF //海拔高度 | |
ExifInterface.TAG_GPS_TIMESTAMP //时间戳 | |
ExifInterface.TAG_GPS_DATESTAMP //日期戳 | |
ExifInterface.TAG_WHITE_BALANCE //白平衡 | |
ExifInterface.TAG_FOCAL_LENGTH //焦距 | |
ExifInterface.TAG_GPS_PROCESSING_METHOD //用于定位查找的全球定位系统处理方法。 |
其中TAG_SUBSEC_TIME 、TAG_SUBSEC_TIME_ORIG 、TAG_SUBSEC_TIME_DIG 没有加注释,我也没查清楚具体是什么意思,但是看log,三个值是一样的。有知道的朋友可以跟我说下,谢谢!
细心的朋友会发现,上面所有的取值都是用的一个方法:exifInterface.getAttribute(String tag),其实ExifInterface还提供了其它方法。
exifInterface.getAltitude(long default); //返回海拔高度,单位米,如果exif的tag不存在,返回默认值。 exifInterface.getAttributeDouble(String tag, Double default) //返回double值,传入默认值 exifInterface.getAttributeInt(String tag, int default) //返回int值,传入默认值 exifInterface.getLatLong(float[] value) //返回纬度和经度,数组第一个是纬度,第二个是经度
二、写入
相对读取,写入就简单很多了。
ExifInterface exifInterface = new ExifInterface(filePath); | |
exifInterface.setAttribute(ExifInterface.TAG_GPS_ALTITUDE,"1/1000"); | |
exifInterface.setAttribute(ExifInterface.TAG_ORIENTATION,"6"); | |
exifInterface.setAttribute(ExifInterface.TAG_IMAGE_WIDTH,"2000"); | |
exifInterface.saveAttributes(); |
代码很简答,但有一点需要说下,setAttributes只是设置属性值,没有保存,saveAttributes才真正保存,但是这个方法比较耗时,不要每set一次都save,全部set完后,再统一save一次。 有一点很尴尬,saveAttributes()这个方法内部会遍历保存所有的值,哪怕你只改变了其中一个值。
三、缩略图
getThumbnail()这个方法可以生成一个缩略图,返回一个字节数组,得到字节数组就可以轻松生成Bitmap。
但是在调用这个方法前,最好先调用exifInterface.hasThumbnail()判断一下是否有缩略图。
getThumbnail()这个方法调用的是native方法,所以具体的实现就看不到了,我也不知道生成的缩略图的分辨率是多少。。。
总结:
以上就是Android中操作Exif信息的全部内容,如果有更新我再修改。 本期节目就到这里,感谢大家的收看,我们下期再见~