自定义相机活动中的Android图片方向问题

13

我编写了一个自定义相机活动来处理在调用意图图像捕获时遇到的某些Android设备的问题。用户能够选择保存图像或仅使用从OnPictureTakenCallback返回的数据。

我的问题是如何正确显示拍摄方向的图像,我通过调用SetRequestedOrientation强制将活动显示为纵向。

当用户拍照时,我如何知道相机的正确方向?例如,用户可能以90度(纵向)的旋转拍照。

我尝试使用窗口管理器的默认显示getRotation(),但是设置请求的方向为纵向后,它只返回Surface.ROTATION_0

更新:为了澄清我的另一个问题,如果用户不保存图像,我该如何仅从图片回调中的byte[]数据确定方向?

更新:在尝试下面的答案之后,我得到的仅为ExifInterface.ORIENTATION_NORMAL。此外,我已经更改了代码,只保存从相机返回的文件,因为我不确定是否有一种简单的方法可以仅通过byte[]数据确定方向。

    private PictureCallback mPicture = new PictureCallback() 
    {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) 
        {
            File directory = new File(android.os.Environment.getExternalStoragePublicDirectory(android.os.Environment.DIRECTORY_PICTURES),
                    "MyApp");
            if(!directory.exists())
            {
                if(!directory.mkdirs())
                {
                    Log.d("CAMERA", "Unable to create directory to save photos.");
                    return;
                }
            }
            File file = new File(directory.getPath() + file.separator + "IMG_" + SimpleDateFormat.getDateTimeInstance().toString() + ".jpg");
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(data);
            fos.close();
            ExifInterface exif = new ExifInterface(file.getCanonicalPath());
            int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
            int rotate = 0;

            switch (orientation) 
            {
                case ExifInterface.ORIENTATION_ROTATE_90:
                   rotate = 90;
                   break; 
                case ExifInterface.ORIENTATION_ROTATE_180:
                   rotate = 180;
                   break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                   rotate = 270;
                   break;
                case default:
                   break;
             }
        }
    };

有人能帮忙吗?https://dev59.com/cofca4cB1Zd3GeqPlaPJ - user4050065
4个回答

15

所以你在拍照时遇到了方向的问题。

这个链接展示了一个简单的相机捕获应用的示例: http://labs.makemachine.net/2010/03/simple-android-photo-capture/

也许你可以尝试通过以下方法来解决方向问题:

          ExifInterface exif = new ExifInterface(_path);
          int exifOrientation = exif.getAttributeInt(
          ExifInterface.TAG_ORIENTATION,
          ExifInterface.ORIENTATION_NORMAL);

          int rotate = 0;

          switch (exifOrientation) {
          case ExifInterface.ORIENTATION_ROTATE_90:
          rotate = 90;
          break; 

         case ExifInterface.ORIENTATION_ROTATE_180:
         rotate = 180;
         break;

         case ExifInterface.ORIENTATION_ROTATE_270:
         rotate = 270;
         break;
         }

           if (rotate != 0) {
          int w = bitmap.getWidth();
          int h = bitmap.getHeight();

// Setting pre rotate
          Matrix mtx = new Matrix();
          mtx.preRotate(rotate);

         // Rotating Bitmap & convert to ARGB_8888, required by tess
         bitmap = Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, false);
         bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
       }

1
我在picturecalback方法中使用了这段代码来旋转图片,但不知何故它没有起作用。你能帮助我吗?如果你能提供帮助,我会给你点赞的。 - Nitin
你遇到了什么问题?这段代码用于调整方向。你可以轻松配置createBitmap函数和Matrix - Android2390
2
这对我非常有效。我需要解决的一个问题是获取位图实例,如下所示:bitmap = BitmapFactory.decodeFile(imagePath, options); 感谢分享这个全面的解决方案。 - Gene Bo
我遇到了同样的问题,需要帮助。https://dev59.com/cofca4cB1Zd3GeqPlaPJ - user4050065
不知道是否能帮到你,但你应该阅读这个答案 - MiguelHincapieC
显示剩余2条评论

4
你需要读取原始JPEG文件的元数据,以验证照片拍摄时的方向。
ExifInterface exif = new ExifInterface(SourceFileName);
String exifOrientation = exif.getAttribute(ExifInterface.TAG_ORIENTATION);

来源: 如何在没有 ExifInterface 的情况下确定图片的方向?

编辑: 回答您的编辑,您是否尝试过使用传递给回调函数的 Camera 对象中可用的 getCameraInfo() 方法?它是否具有您需要的信息?

来源:http://developer.android.com/reference/android/hardware/Camera.html


你应该能够在CameraInfo上调用"orientation"。http://developer.android.com/reference/android/hardware/Camera.CameraInfo.html - bsempe
根据文档,此功能自API级别9(即Android 2.3)起可用。我的应用最低API级别为8。 - Bryan

3
public void surfaceCreated(SurfaceHolder holder) {
    try {
        mCamera.setPreviewDisplay(holder);
        Camera.Parameters parameters = mCamera.getParameters();
        if (this.getResources().getConfiguration().orientation !=
                Configuration.ORIENTATION_LANDSCAPE)
        {
            parameters.set("orientation", "portrait"); <----THis gets the job done!!!
            // For Android Version 2.2 and above
            mCamera.setDisplayOrientation(90);
            // For Android Version 2.0 and above
            parameters.setRotation(90);
        }


        // End Effects for Android Version 2.0 and higher
        mCamera.setParameters(parameters);
    }
    catch (IOException exception)
    {
        mCamera.release();
    }

}

3

移除setRequestedOrientation()方法后,getWindowManager().getDefaultDisplay().getRotation()可以正确地获取旋转角度。我猜测设置请求方向会阻止活动在配置更改时重新绘制自身,因此设备不知道任何旋转变化。现在我的唯一问题是从0度方向的横屏模式切换到180度旋转的横屏模式不会触发这个事件:

@Override
public void onConfigurationChanged(Configuration newconfig)
{
    super.onConfigurationChanged(newconfig);

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接