什么是 Android 中的 ExifInterface?
我们在应用程序中大量使用图像。对于某些与图片相关的应用程序,所有图像信息都是必需的。但是,我们不能总是立即从图像中读取图像的特征。可能需要了解图像信息,例如 GPS 位置、日期/时间、拍摄时的设置、方向等。以前,我们必须分别从不同的技术中提取元数据并读取它以理解图像属性。即使更改照片,例如删除 GPS 标签或更改方向,在我们阅读时也将是一项艰巨的工作。 Exif 文件和 ExifInterface 是这些问题的答案。
Exif 究竟是什么?
Ex changeable I mage File Format (Exif) 是可交换图像文件格式的首字母缩写。这是一个标准,它指定有关相机记录的照片或其他媒体的详细信息。它可以保存关键信息,例如相机曝光、拍摄图像的日期/时间,甚至 GPS 位置。
以下是 Exif 文件的示例:
如果您查看上面的图像,您会注意到它具有图像长度和宽度、图像捕获日期和时间、捕获图像的设备、方向代码等属性,以及一些图像属性,例如光线、白平衡、焦距、闪光灯是否打开,以及图像的 GPS 信息,即拍摄图像的纬度。只需凝视它,我们就可以看到图像的所有特征。您现在应该对 EXIF 文件有了很好的了解。
如何在 Android 上获取 EXIF 数据?
我们通过在 Android 中使用 ExifInterface 了解了 Exif 是什么以及它包含什么。下面我们来看看如何从Android上的图片中获取Exif数据。从 25.1.0 版本开始,ExifInterface 已包含在 android 支持库中。尽管该功能自 Android 7.1 以来就已经存在,并且为 UI 提供了所有可能性,但它仅在 Android 9+ 中才有意义。这已通过 100 多个用于读取 Exif 标签的特性得到增强,其中包括有关相机、相机设置、方向和 GPS 坐标的信息
It can only read the Exif of JPEG files or a RAW picture file at the moment. JPEG, DNG, CR2, NEF, NRW, ARW, RW2, ORF, PEF, SRW, RAF, and HEIF are all supported formats.
如果您希望使用 ExifInterface,您必须将以下依赖项添加到您的 build.gradle。
implementation 'androidx.exifinterface:exifinterface:1.3.2'
关于 Exif 数据要记住的一件事是没有强制性标签:每个标签都是可选的,有些服务甚至完全删除 Exif 数据。因此,您应该始终处理没有 Exif 数据的实例,无论是因为没有单个属性的数据,还是因为图像格式根本无法像臭名昭著的 WebP 格式那样链接数据
什么是 Exif 属性以及如何读取它们?
让我们看看 ExifInterface 如何从各种来源和一些使用案例中读取 EXIF 特征。对于大多数属性,您只需使用 getAttributeInt()、getAttributeDouble() 或 getAttribute()(对于字符串)方法。
用于从内容中提取数据的 Uri:
Kotlin
Uri gfgUri; // the file uri
InputStream gfgIn;
try {
gfgIn = getContentResolver().openInputStream(gfgUri);
ExifInterface exifInterface = new ExifInterface(gfgIn);
// Extract the EXIF tag here
} catch (IOException e) {
// Handle any errors
} finally {
if (gfgIn != null) {
try {
gfgIn.close();
} catch (IOException ignored) {}
}
}
Kotlin
var gfgExif : ExifInterface = ExifInterface(pictureFile.getPath())
gfgExif.setAttribute(ExifInterface.TAG_ORIENTATION, "" + getPhotoOrientation(configurationProvider.getSensorPosition()))
gfgExif.saveAttributes()
Java
int gfgRoatation = 0;
int gfgOrientation = exifInterface.getAttributeInt(
ExifInterface.TAG_GFGORIENTATION ,
ExifInterface.GFGORIENTATION _UNDEFINED);
switch (gfgOrientation ) {
case ExifInterface.GFGORIENTATION _ROTATE_90:
gfgRoatation = 180;
break;
case ExifInterface.GFGORIENTATION _ROTATE_180:
gfgRoatation = 0;
break;
case ExifInterface.GFGORIENTATION _ROTATE_270:
gfgRoatation = 270;
break;
}
Java
ExifInterface gfgexif = new ExifInterface(uri.getPath());
Java
int gfgrotation = gfgexif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);
Java
int gfgDegRotation = exifToDegrees(gfgRotation);
Java
Matrix gfgMatrix = new Matrix();
if (gfgrotation != 0) {
gfgMatrix.postRotate(rotationInDegrees);
}
Java
Bitmap.createBitmap(Bitmap source, int x, int y, int width)
GeekTip: that external InputStreams, such as those returned by a HttpURLConnection, will not function with ExifInterface. It is strongly advised that they only be used with content:/ or file:/ URIs.
对于相机应用程序:
一旦图像被捕获,写入属性就变得更加重要。暂时还仅限于JPEG图片。我们可以使用 ExifInterface 简单地更改 JPEG ORIENTATION、JPEG GPS LOCATION 或等效项。根据用户的要求,我们也可以删除这些特征。
科特林
var gfgExif : ExifInterface = ExifInterface(pictureFile.getPath())
gfgExif.setAttribute(ExifInterface.TAG_ORIENTATION, "" + getPhotoOrientation(configurationProvider.getSensorPosition()))
gfgExif.saveAttributes()
图像方向:
它保存在适当称为 TAG ORIENTATION 中,它产生 ORIENTATION_ 常量之一,是呈现图片时最重要的属性之一。您可以对该值进行后处理以将其转换为旋转角度。
Java
int gfgRoatation = 0;
int gfgOrientation = exifInterface.getAttributeInt(
ExifInterface.TAG_GFGORIENTATION ,
ExifInterface.GFGORIENTATION _UNDEFINED);
switch (gfgOrientation ) {
case ExifInterface.GFGORIENTATION _ROTATE_90:
gfgRoatation = 180;
break;
case ExifInterface.GFGORIENTATION _ROTATE_180:
gfgRoatation = 0;
break;
case ExifInterface.GFGORIENTATION _ROTATE_270:
gfgRoatation = 270;
break;
}
第 1 步:首先创建 ExifInterface:
Java
ExifInterface gfgexif = new ExifInterface(uri.getPath());
步骤#2:然后使用 Exif 旋转角度旋转位图:
Java
int gfgrotation = gfgexif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);
第 3 步:要将 Exif 旋转转换为度数,请使用以下公式:
Java
int gfgDegRotation = exifToDegrees(gfgRotation);
步骤#4:然后,使用矩阵,使用图像的实际旋转作为参考点旋转图片:
Java
Matrix gfgMatrix = new Matrix();
if (gfgrotation != 0) {
gfgMatrix.postRotate(rotationInDegrees);
}
步骤#5:Bitmap.createBitmap函数,它接受一个矩阵作为输入,用于制作新的旋转图像:
Java
Bitmap.createBitmap(Bitmap source, int x, int y, int width)
瞧,EXIF 数据已创建!
如何使用 ExifInterface 的一些示例
- 拍照时,ExifInterface 用于写入图像信息。在将图像存储在手机内存中时,跟踪图像的方向也很有用。
- 我们可能需要缩小图片大小并更新Exif信息;在这种情况下,我们需要获取 Exif 信息并将新信息保存回图像。
- 还使用 ExifInterface 检索和解析图像标题。
- 转动设备时,视觉方向保持一致。
- 从图库中获取图片并以适当的方向和与图像一起保存的其他数据呈现。