【问题标题】:How can I get the device orientation when a photo was taken拍摄照片时如何获取设备方向
【发布时间】:2017-10-12 22:09:52
【问题描述】:

我从来没有像今天这样在图像上苦苦挣扎,我会很感激一些帮助 :D
所以,事情是,我正在使用内置摄像头拍摄照片,然后将其发送到后端以保存它,但Kit kat 和特别是Samsung 设备的方向搞砸了。我尝试使用大家建议的exif 界面,但我无法获得照片方向。
几分钟前我找到了一个与此相关的答案,说也许一个好的解决方案是在拍照时保存设备方向,这听起来很不错,但是,我不知道如何使用内置在相机中,因为使用Intent 打开相机时我没有完全控制权,如下所示:

mPathToTakenImage = ImageProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".provider",
            newFile);

    openCamera.putExtra(MediaStore.EXTRA_OUTPUT, mPathToTakenImage);
    openCamera.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

    startActivityForResult(openCamera, AlgebraNationConstants.TAKE_PHOTO_REQUEST_CODE);

那么,如何在拍摄图像时获取设备方向以便正确旋转图像?
这是旋转图像的代码,但是,我总是得到零:

        final Bitmap finalImg;
        final StringBuilder base64Image = new StringBuilder("data:image/jpeg;base64,");

        final ExifInterface exifInterface;

        try {
            final String imagePath = params[0].getPath();

            exifInterface = new ExifInterface(imagePath);

            final int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_UNDEFINED);

            final Bitmap takenPhoto = MediaStore.Images.Media.getBitmap(mRelatedContext.getContentResolver(),
                    params[0]);

            if (null == takenPhoto) {
                base64Image.setLength(0);
            } else {
                finalImg = rotateBitmap(takenPhoto, orientation);

                if (null == finalImg) {
                    base64Image.setLength(0);
                } else {
                    final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                    finalImg.compress(Bitmap.CompressFormat.JPEG, 75, byteArrayOutputStream);
                    final byte[] byteArray = byteArrayOutputStream.toByteArray();
                    base64Image.append(Base64.encodeToString(byteArray, Base64.DEFAULT));
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

        return base64Image.length() == 0 ? null : base64Image.toString();

我快疯了,任何帮助都将不胜感激。

编辑:

【问题讨论】:

  • final String imagePath = params[0].getPath(); -- 这到底是什么?它应该是newFile(或者,因为它是String,所以newFile.getAbsolutePath()
  • 感谢您的回复。该代码在Asynctask 类中调用,其中params[0]Uri
  • Uri 是从哪里来的?您已经知道图像应该在哪里 (newFile),而那不是 Uri。除非Uri 是您使用Uri.fromFile() 创建的,否则getPath() 毫无意义。
  • 当图像来自相机时,Uri 是我在Intent 中额外传递的那个,否则在onActivityResult 中使用data.getData()

标签: android camera rotation exif


【解决方案1】:

Uri 不是文件。除非Uri 的方案是file,否则getPath() 是没有意义的。在您的情况下,该方案主要是content,而不是file。就目前而言,您没有获得 EXIF 标头,因为 ExifInterface 找不到该文件。

使用ContentResolveropenInputStream()Uri 标识的内容上打开InputStream。将InputStream 传递给the android.support.media.ExifInterface constructor

另外,请记住,OutOfMemoryError 会在很多时候崩溃,因为您将没有堆空间来保存 base64 编码的照片。

【讨论】:

  • 我知道Uri 不是文件。不幸的是,我的应用 minSdk 是 16,而您提到的构造函数是
  • @pamobo0609:我提到的构造函数来自ExifInterface的支持库版本——即the one that I linked to in my answer。它可以回溯到 API 级别 14,并且不受 the security flaws that the ExifInterface that you are presently using have on older Android devices 的影响。
  • 我改变了它,我仍然得到零,使用你建议的InputStreamexifInterface = new ExifInterface(new FileInputStream(params[1])); final int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);
  • 从设备上下载图像并使用其他工具(例如,exiftool)检查它是否具有该标题。理想情况下,相机应用会设置标题,但没有要求这样做。
  • @pamobo0609:您需要筛选该输出并查看方向标头是否存在。我在屏幕截图中看不到它,但输出还有更多内容。
【解决方案2】:

所以,我终于利用这两个答案解决了我的问题:

https://stackoverflow.com/a/17426328

https://stackoverflow.com/a/40865982

一般来说,问题是由于磁盘中的图像分配,因为我不知道为什么Android 不喜欢我提供自己的路径来保存拍摄的图像这一事实。最后打开相机的Intent是这样的:
final Intent openCamera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(openCamera, AlgebraNationConstants.TAKE_PHOTO_REQUEST_CODE);

Android 本身正在解决图像的放置位置。不过,@CommonsWare 感谢您的启发和回答。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多