Android Camera2 图片在图库中出现旋转
Android Camera2 pictures appear rotated in gallery
我制作了一个使用 Google Camera2 sample 拍照(人像、风景或自拍)的应用程序。一切正常,我可以拍照,它们被保存等等
但是当我打开 phone 的 (Samsung S7) 图库时,所有自拍和人像图片都旋转了 90 度。风景照还是不错的。我看过很多 post 关于如何以正确的方向 读取 图像,但是如何正确保存它们呢?
我的应用程序中有自己的图库,并且图片在没有任何特殊旋转修复的情况下正确加载(使用 Glide),所以我不确定我做错了什么,最重要的是,我该如何解决这个问题?
图像查看器应该检查 EXIF 标签并根据方向标签旋转图像。这允许相机应用程序和类似软件以任何方向保存图像,而无需在保存前旋转图像。
像 Glide 和 Picasso 这样的库会为你做这件事,前提是你允许它们访问完整的 JPEG(例如,file
Uri
、content
Uri
、 https
URL)。这是因为他们可以访问 EXIF 标签 和 结果 ImageView
,因此他们可以告诉 ImageView
旋转图像。
然而,并不是每个人都使用这样的库。 ImageView
自己处理诸如 Bitmap
之类的事情,其中那些 EXIF 标签在解码过程中丢失了。
作为相机应用程序的作者,您在这里有两个主要选择:
你可以查看EXIF标签,看到图片需要旋转,自己旋转,保存旋转后的图片(去除orientation标签,安排保留其他)。但是,这可能会因 OutOfMemoryError
而失败,特别是对于相机图像,因为这些图像往往很大。
你可以耸耸肩继续前进,因为这真的不是你的问题。正如您所注意到的,其他图库应用程序没有出现此问题,因为它们已经过充分测试,而您尝试的原始图库应用程序没有。
如果您选择选项 #1,如果您得到 OutOfMemoryError
,它将变成选项 #2。
您是否在静态捕获请求中使用了 JPEG_ORIENTATION 控件?如果不是,那可能是问题所在 - 该控件告诉相机设备如何将最终的 JPEG 图像旋转为正面朝上。
因此您需要更新该控件中的值以描述图像传感器当前相对于世界的排列方式。
要进行该计算,您需要来自加速度计的输入(它会告诉您哪条路向下),然后是一些基本的数学运算 - 从上面的 link 重现:
private int getJpegOrientation(CameraCharacteristics c, int deviceOrientation) {
if (deviceOrientation == android.view.OrientationEventListener.ORIENTATION_UNKNOWN) return 0;
int sensorOrientation = c.get(CameraCharacteristics.SENSOR_ORIENTATION);
// Round device orientation to a multiple of 90
deviceOrientation = (deviceOrientation + 45) / 90 * 90;
// Reverse device orientation for front-facing cameras
boolean facingFront = c.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT;
if (facingFront) deviceOrientation = -deviceOrientation;
// Calculate desired JPEG orientation relative to camera orientation to make
// the image upright relative to the device orientation
int jpegOrientation = (sensorOrientation + deviceOrientation + 360) % 360;
return jpegOrientation;
}
其中输入 deviceOrientation 来自传感器 API。
我制作了一个使用 Google Camera2 sample 拍照(人像、风景或自拍)的应用程序。一切正常,我可以拍照,它们被保存等等
但是当我打开 phone 的 (Samsung S7) 图库时,所有自拍和人像图片都旋转了 90 度。风景照还是不错的。我看过很多 post 关于如何以正确的方向 读取 图像,但是如何正确保存它们呢?
我的应用程序中有自己的图库,并且图片在没有任何特殊旋转修复的情况下正确加载(使用 Glide),所以我不确定我做错了什么,最重要的是,我该如何解决这个问题?
图像查看器应该检查 EXIF 标签并根据方向标签旋转图像。这允许相机应用程序和类似软件以任何方向保存图像,而无需在保存前旋转图像。
像 Glide 和 Picasso 这样的库会为你做这件事,前提是你允许它们访问完整的 JPEG(例如,file
Uri
、content
Uri
、 https
URL)。这是因为他们可以访问 EXIF 标签 和 结果 ImageView
,因此他们可以告诉 ImageView
旋转图像。
然而,并不是每个人都使用这样的库。 ImageView
自己处理诸如 Bitmap
之类的事情,其中那些 EXIF 标签在解码过程中丢失了。
作为相机应用程序的作者,您在这里有两个主要选择:
你可以查看EXIF标签,看到图片需要旋转,自己旋转,保存旋转后的图片(去除orientation标签,安排保留其他)。但是,这可能会因
OutOfMemoryError
而失败,特别是对于相机图像,因为这些图像往往很大。你可以耸耸肩继续前进,因为这真的不是你的问题。正如您所注意到的,其他图库应用程序没有出现此问题,因为它们已经过充分测试,而您尝试的原始图库应用程序没有。
如果您选择选项 #1,如果您得到 OutOfMemoryError
,它将变成选项 #2。
您是否在静态捕获请求中使用了 JPEG_ORIENTATION 控件?如果不是,那可能是问题所在 - 该控件告诉相机设备如何将最终的 JPEG 图像旋转为正面朝上。
因此您需要更新该控件中的值以描述图像传感器当前相对于世界的排列方式。
要进行该计算,您需要来自加速度计的输入(它会告诉您哪条路向下),然后是一些基本的数学运算 - 从上面的 link 重现:
private int getJpegOrientation(CameraCharacteristics c, int deviceOrientation) {
if (deviceOrientation == android.view.OrientationEventListener.ORIENTATION_UNKNOWN) return 0;
int sensorOrientation = c.get(CameraCharacteristics.SENSOR_ORIENTATION);
// Round device orientation to a multiple of 90
deviceOrientation = (deviceOrientation + 45) / 90 * 90;
// Reverse device orientation for front-facing cameras
boolean facingFront = c.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT;
if (facingFront) deviceOrientation = -deviceOrientation;
// Calculate desired JPEG orientation relative to camera orientation to make
// the image upright relative to the device orientation
int jpegOrientation = (sensorOrientation + deviceOrientation + 360) % 360;
return jpegOrientation;
}
其中输入 deviceOrientation 来自传感器 API。