`

Android 下的EXIF

阅读更多
转自:http://dev.10086.cn/cmdn/wiki/index.php?edition-view-6817-1.html

一.什么是Exif
Exif(Exchangeable Image File 可交换图像文件)是一种图象文件格式,它的数据存储与JPEG格式是完全相同的。实际上Exif格式就是在JPEG格式头部插入了数码照片的信息,包括拍 摄时的光圈、快门、白平衡、ISO、焦距、日期时间等各种和拍摄条件以及相机品牌、型号、色彩编码、拍摄时录制的声音以及全球定位系统(GPS)、缩略图 等。简单地说,Exif=JPEG+拍摄参数。因此,你可以利用任何可以查看JPEG文件的看图软件浏览Exif格式的照片,但并不是所有的图形程序都能 处理 Exif信息。

所有的JPEG文件以字符串“0xFFD8”开头,并以字符串“0xFFD9”结束。文件头中有一系列“0xFF??”格式的字符串,称为“标识”,用来 标记JPEG文件的信息段。“0xFFD8”表示图像信息开始,“0xFFD9”表示图像信息结束,这两个标识后面没有信息,而其它标识紧跟一些信息字 符。
  0xFFE0 -- 0xFFEF之间的标识符称为“应用标记”,没有被常规JPEG文件利用,Exif正是利用这些信息串记录拍摄信息如快门速度、光圈值等,甚至可以包括全 球定位信息。按照Exif2.1标准对这些标识符的定义,数码相机可以把各种拍摄信息记入数码图像中,应用软件可以读取这些数据,再按照Exif2.1标 准,检索出它们的具体含义,一般而言包括以下一些信息:
  Image Description 图像描述、来源. 指生成图像的工具
  Artist作者 有些相机可以输入使用者的名字
  Make 生产者 指产品生产厂家
  Model 型号 指设备型号
  Orientation方向 有的相机支持,有的不支持
  XResolution/YResolution X/Y方向分辨率 本栏目已有专门条目解释此问题。
  ResolutionUnit分辨率单位 一般为PPI
  Software软件 显示固件Firmware版本
  DateTime日期和时间
  YCbCrPositioning 色相定位
  ExifOffsetExif信息位置,定义Exif在信息在文件中的写入,有些软件不显示。
  ExposureTime 曝光时间 即快门速度
  FNumber光圈系数
  ExposureProgram曝光程序 指程序式自动曝光的设置,各相机不同,可能是Sutter Priority(快门优先)、Aperture Priority(快门优先)等等。
  ISO speed ratings感光度
  ExifVersionExif版本
  DateTimeOriginal创建时间
  DateTimeDigitized数字化时间
  ComponentsConfiguration图像构造(多指色彩组合方案)
  CompressedBitsPerPixel(BPP)压缩时每像素色彩位 指压缩程度
  ExposureBiasValue曝光补偿。
  MaxApertureValue最大光圈
  MeteringMode测光方式, 平均式测光、中央重点测光、点测光等。
  Lightsource光源 指白平衡设置
  Flash是否使用闪光灯。
  FocalLength焦距,一般显示镜头物理焦距,有些软件可以定义一个系数,从而显示相当于35mm相机的焦距 MakerNote(User Comment)作者标记、说明、记录
  FlashPixVersionFlashPix版本 (个别机型支持)
  ColorSpace色域、色彩空间
  ExifImageWidth(Pixel X Dimension)图像宽度 指横向像素数
  ExifImageLength(Pixel Y Dimension)图像高度 指纵向像素数
  Interoperability IFD通用性扩展项定义指针 和TIFF文件相关,具体含义不详
  FileSource源文件 Compression压缩比。

二.Camera中拍照流程

在Android Camera程序开发过程中,要用到Exif相关的知识,如果处理不当,会导致拍摄的JPEG图片无法正常浏览。
在Froyo(Android 2.2)源码中的Camera应用是不对Exif信息进行写操作,而只是读操作,对于Exif的写操作是交给Camera硬件抽象层去完成,这是 google的设计逻辑。但是不同的Android平台及其相关子平台,再加上不同的Camera应用,相互交替,排列组合,或许会出现这样一种情况:底 层没有去写Exif,而上层应用也没有写Exif信息,那么图片的显示信息将会丢失。其中影响最为严重的是Orientation这个参数。

Froyo camera的逻辑是这样的:
在Camera这个Activity中,有一个内部类ImageCapture,其中包含一个重要的方法:

复制到剪贴板  Java代码
private void capture() {  
// Set rotation.  
mParameters.setRotation(mLastOrientation);  
....................  
.....................  
mCameraDevice.setParameters(mParameters);  
 
mCameraDevice.takePicture(mShutterCallback, mRawPictureCallback, mPostViewPictureCallback, new JpegPictureCallback(loc));  
}  
 
大致流程是这样的:
1.将拍照时相机的方向添加进Camera.Parameters的实例中;
2.将全部相机拍照参数传给android.hardware.Camera的对象;
3.调用方法takePicture,并设置好非常重要的4个callback;
4.生成Exif数据的事情就由HAL来完成;
5.第4个callback返回数据(这个callback是最重要的,而且是不可缺省的,也就是说前3个callback设置成Null也不会影响拍照功能),见如下代码:

复制到剪贴板  Java代码
 
private final class JpegPictureCallback implements PictureCallback {  
public void onPictureTaken(final byte[] jpegData, final android.hardware.Camera camera) {  
//jpegData为JPEG数据,是由HAL层根据应用传输的各种参数(即Camera.Parameters的实例)以及JPEG压缩算法生成的。  
mImageCapture.storeImage(jpegData, camera, mLocation);  
}  
}  
三.Exif使用方法及代码优化方案

什么地方用到Exif信息呢?我遇到的至少有如下这么几个地方:
1.生成右上角所略图;
2.图片显示应用,例如android自带的gallery3d应用;
3.图片回显;
4.短(彩)信等需要添加camera附件的应用.

看看源码: ImageManager中是这样读取Exif方向参数的。

复制到剪贴板  Java代码
public static int getExifOrientation(String filepath) {  
    int degree = 0;  
    ExifInterface exif = null;  
    try {  
        exif = new ExifInterface(filepath);  
    } catch (IOException ex) {  
        Log.e(TAG, "cannot read exif", ex);  
    }  
    if (exif != null) {  
        int orientation = exif.getAttributeInt(  
            ExifInterface.TAG_ORIENTATION, -1);  
        if (orientation != -1) {  
            // We only recognize a subset of orientation tag values.  
            switch(orientation) {  
                case ExifInterface.ORIENTATION_ROTATE_90:  
                    degree = 90;  
                    break;  
                case ExifInterface.ORIENTATION_ROTATE_180:  
                    degree = 180;  
                    break;  
                case ExifInterface.ORIENTATION_ROTATE_270:  
                    degree = 270;  
                    break;  
            }  
 
        }  
    }  
    return degree;  
}  
这个方法可以进一步优化,从而对于Exif信息的写入不再依赖底层。那就是比较一下传输给底层的orientation与实际返回的是否相等,不相等就是底层写入Exif信息出错,我们就可以在应用层进行修正。
可以添加一个判断分支如下:(其中EXIF_ORIENTATION是我们缓存的应用传给底层的值)。

复制到剪贴板  Java代码
else if(orientation == 0 && EXIF_ORIENTATION != 0) {  
                switch (EXIF_ORIENTATION) {  
                case 90:  
                    orientation = ExifInterface.ORIENTATION_ROTATE_90;  
                    degree = 90;  
                    break;  
                case 180:  
                    orientation = ExifInterface.ORIENTATION_ROTATE_180;  
                    degree = 180;  
                    break;  
                case 270:  
                    orientation = ExifInterface.ORIENTATION_ROTATE_270;  
                    degree = 270;  
                    break;  
                }  
                exif.setAttribute(ExifInterface.TAG_ORIENTATION, Integer.toString(orientation));  
                try {  
                    exif.saveAttributes();  
                } catch (IOException e) {  
                     Log.e(TAG, "cannot save exif", e);  
                }  
            } 

在应用层对于Exif的操作是通过android.media.ExifInterface接口完成的。
通过public void setAttribute (String tag, String value) 来设置,而获取可以通过 public int getAttributeInt (String tag, int defaultValue) 和 public String getAttribute (String tag) 两种方法都可以,getAttributeInt 重载方法一第二个参数为我们设置的默认值,如果成功则返回相应Tag的值;特定的整数内容为该方法直接返回值。而重载方法二该方法直接返回结果,如果失败 则为null。

结论
这样,经过简单改造(只是添加了对Exif信息校验以及写操作的逻辑)的Camera应用将更加健壮,不依赖平台底层是否处理了Exif信息,即使出现异常,应用能够自动修正。
这里只是以Exif中的 Orientation参数为例,其他参数可以以此类推,保证拍摄出来的图片符合标准。
分享到:
评论

相关推荐

    exif.rar_android_android exif_exif_exif java

    在Android平台上,开发人员经常需要处理图像数据,其中包括解析图像元数据,特别是Exif(Exchangeable Image File Format)信息。Exif是一种标准,允许在JPEG和TIFF图像文件中存储额外的信息,如拍摄时间、地理位置...

    Android-Exif-Extended:适用于Android的Exif扩展库,基于jhead c库(http

    Android-Exif-扩展 描述 适用于Android的Exif库。 它基于android [ExifInterface] 和[Jhead] c库 进口 只需将此行添加到您的依赖项组中: compile 'it.sephiroth.android.exif:library:+' 用法 import it.sephiroth...

    Andriod下读取图片Exif信息Demo

    在Android平台上,开发人员经常需要处理图像数据,其中包括读取图片的Exif信息。Exif(Exchangeable Image File Format)是一种扩展的JPEG格式,用于存储与图像相关的信息,如拍摄日期、时间、地理位置、相机型号、...

    Android下的EXIF是什么

    在Android系统中,EXIF信息通常包含在JPEG格式的图像文件中,提供了关于照片的各种详细拍摄参数。这些参数包括但不限于: 1. **拍摄参数**:Exif信息记录了拍摄时的光圈、快门速度、ISO感光度、焦距、白平衡设置、...

    android-exif:Exif 测试

    Android Exif“问题”测试 有时保存图片时设置了 Exif 旋转(例如:图片保存时旋转 90 度),而不是正确显示此图片,无论谁显示它,都应该在显示之前旋转图片。 因此,如果我在下载图片后(从字节 [] 或将图片保存...

    Android ExifInterface

    ExifInterface是Android SDK提供的一款用于读取和修改图片元数据的工具类,特别是与Exchangeable Image File Format(EXIF)相关的数据。EXIF是一种标准,用于存储图像和音频文件的附加信息,如拍摄时间、地点、相机...

    Android中通过Exifinterface读取图片地理位置信息

    ExifInterface是Android SDK提供的一种接口,专门用于读取和写入JPEG文件的Exchangeable Image File Format (EXIF)元数据。下面将详细解释如何使用ExifInterface来读取图片的地理位置信息。 首先,了解什么是EXIF...

    Exif信息获取

    下面我们将深入探讨如何在Android应用中获取Exif信息。 1. **ExifInterface类的使用** Android SDK提供了一个名为`ExifInterface`的类,用于处理Exif信息。首先,你需要创建一个`ExifInterface`实例,传入图片文件...

    通过一个函数就可以方便的获取图片的exif和iptc信息包含gps地理位置等

    在IT行业中,图片处理是一项常见的任务,而图片的元数据如EXIF和IPTC信息则是其中的关键部分。这些信息包含了大量的图像属性,比如拍摄时间、相机型号、曝光参数、作者信息,甚至GPS地理位置等。在uni-app这个跨平台...

    Android下使用Camera硬件拍照Demo

    Android提供了`ExifInterface`类来读取和修改JPEG图片的EXIF信息,其中包括旋转角度。 此外,当不再需要相机时,必须释放资源,调用`Camera.release()`关闭相机,避免内存泄漏和资源浪费。同时,如果在预览过程中...

    Android 图片属性信息修改(定位信息修改).rar

    首先,Android系统提供了一个名为ExifInterface的API,它允许开发者读取和修改JPEG图像的Exchangeable image file format (EXIF)元数据。EXIF信息通常包含拍摄日期、时间、相机型号、曝光参数等,还包括GPS定位信息...

    android如何获取相片的拍摄日期

    - `ExifInterface`是Android提供的一个类,专门用来处理图像文件的EXIF信息。 - 创建`ExifInterface`对象,传入图片文件的路径,例如:`new ExifInterface(filePath)`。 3. **获取拍摄日期**: - 调用`...

    Photo_Exif_Toolkit:完全使用Kotlin语言编写的Photo Exif Toolkit Android应用

    《全面解析Photo_Exif_Toolkit:Kotlin打造的Android照片元数据神器》 在移动设备上,处理照片的元数据,如EXIF信息,对于摄影师、开发者或是图像处理爱好者来说,是一项重要的任务。Photo_Exif_Toolkit是一款完全...

    Delphi获取照片的Exif信息(英文)..rar

    在IT行业中,Delphi是一种基于Pascal语言的集成开发环境(IDE),用于创建Windows、macOS、iOS和Android平台的应用程序。本主题聚焦于如何在Delphi中获取照片的Exif(Exchangeable Image File Format)信息,这在...

    exif-thumbnail-adder:Android应用程序在不包含JPEG图片的JPEG图片的EXIF标签中添加缩略图(批处理)

    Exif缩略图添加器这是一个适用于android设备的应用程序,它将在您的设备上搜索图片(JPEG),如果还没有缩略图,则在EXIF标签中添加缩略图。 它应该可以在android Oreo(android 8,SDK 26)上运行,并且已经在运行...

    安卓利用CameraX 拍照获这张照片的exif信息

    通过以上步骤,我们就能够利用Android的CameraX库拍摄照片,并获取到照片的EXIF信息。这在创建照片编辑应用、地理位置标记、图像分析等功能时非常有用。了解如何正确处理和解析EXIF信息是提升用户体验的关键,因为它...

    Exif信息查看工具.rar

    Exif信息查看工具是一款专为摄影爱好者和图像处理专业人员设计的应用程序,它能够帮助用户深入解析并修改图片中的Exif(Exchangeable Image File Format)数据。Exif是一种嵌入在JPEG、TIFF等图像文件格式中的元数据...

    Android-Android仿微信的图片选择器带裁剪功能支持圆形和方形裁剪

    6. **图片旋转**: 图片旋转功能可以使用`ExifInterface`读取和修改图片的EXIF信息,从而改变图片的方向。此外,还可以直接使用`Matrix`对象旋转`Bitmap`。 7. **图片压缩**: 图片压缩是为了减少内存占用和提高传输...

    Android 中拍照、相册选择、裁剪照片(兼容Android7.0)

    在Android应用开发中,涉及到用户交互的一个常见任务是允许用户通过拍照或从相册选取照片,并对其进行裁剪,以满足特定尺寸或比例的需求。这里我们将深入探讨如何在Android 7.0及更高版本中实现这一功能,同时确保...

Global site tag (gtag.js) - Google Analytics