安卓前置摄像头拍照时照片颠倒问题的解决方法

18

我的应用程序在纵向模式下运行,作为其中一个活动的一部分,我有一个摄像头对象作为片段在其中运行。

我可以选择从前置摄像头切换到后置摄像头,在使用后置摄像头拍照时一切正常。

但是当我使用前置摄像头拍照时,它们会被倒转180度。现在我知道这可能与方向处于纵向模式有关,但如果将其放在横向模式下,那就会毁掉我的应用程序的想法。

是否有任何方法可以修复此问题,使拍摄的图片与预览中看到的相同?

        listener = new OrientationEventListener(this.getActivity(),SensorManager.SENSOR_DELAY_NORMAL){

        @Override
        public void onOrientationChanged(int orientation) {
            // TODO Auto-generated method stub
            if (orientation == ORIENTATION_UNKNOWN) return;
             android.hardware.Camera.CameraInfo info =
                    new android.hardware.Camera.CameraInfo();
             android.hardware.Camera.getCameraInfo(mCurrentCamera, info);
             orientation = (orientation + 45) / 90 * 90;
             int rotation = 0;
             if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
                 rotation = (info.orientation - orientation + 360) % 360;
             } else {  // back-facing camera
                 rotation = (info.orientation + orientation) % 360;
             }
             if (mCamera.getParameters() != null){
             Camera.Parameters mParameters = mCamera.getParameters();

             mParameters.setRotation(rotation);
             mCamera.setParameters(mParameters);
             }
        }

    };
    listener.enable();
    if (listener.canDetectOrientation())
        Log.d("Orientation Possible", "Orientation Possible");

问题是,当我尝试拍照时,程序会崩溃。即使在预览模式下运行一段时间后也会再次崩溃。还应该补充一点,在另一个方法中我正在做这个操作。

   public void switchCamera(Camera camera) {
    setCamera(camera);
    try {
        camera.setPreviewDisplay(mHolder);
    } catch (IOException exception) {
        Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
    }
    Camera.Parameters parameters = camera.getParameters();
    parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);

    requestLayout();


    try{
        camera.setParameters(parameters);
    }
    catch (RuntimeException ex){
        Log.d("Preview", "Failure to set proper parameters");
        //need to improve this method
        if (mSupportedPreviewSizes != null) {
            Camera.Size cs = mSupportedPreviewSizes.get(0);
            parameters.setPreviewSize(cs.width, cs.height);
            camera.setParameters(parameters);
            requestLayout();
            //int tempheight = mPreviewSize.height;
            //mPreviewSize.height = mPreviewSize.width;
            //mPreviewSize.width = tempheight;

        }
    }

当你在摄像头之间切换时(从后置摄像头切换到前置摄像头或反之亦然),就会调用这个函数。这是否会干扰方向事件监听器?

此外,在保存拍摄的照片时,这是我调用的功能。以前它只接受数据作为参数,但我尝试让它也接受屏幕方向。问题是无论如何屏幕方向始终为90度。因此,位图将永远旋转90度(这对于使用后置摄像头拍照非常好),但当使用前置摄像头拍摄时会翻转它。是否可以在此函数中实现修复?

  public static Bitmap MakeSquare(byte[] data, int orientation) {
    int width;
    int height;
    // Rotate photo
    Matrix matrix = new Matrix();
    matrix.postRotate(orientation);
    // Convert ByteArray to Bitmap
    Bitmap bitPic = BitmapFactory.decodeByteArray(data, 0, data.length);
    width = bitPic.getWidth();
    height = bitPic.getHeight();


    // Create new Bitmap out of the old one
    Bitmap bitPicFinal = Bitmap.createBitmap(bitPic, 0, 0, width, height,matrix, true);
    bitPic.recycle();
    int desWidth;
    int desHeight;
    desWidth = bitPicFinal.getWidth();
    desHeight = desWidth;
    Bitmap croppedBitmap = Bitmap.createBitmap(bitPicFinal, 0,bitPicFinal.getHeight() / 2 - bitPicFinal.getWidth() / 2,desWidth, desHeight);
    croppedBitmap = Bitmap.createScaledBitmap(croppedBitmap, 528, 528, true);
    return croppedBitmap;
}
2个回答

35

嗯,看起来我已经解决了这个问题。我使用了这里的建议:Android前置和后置摄像头方向,横向

并将我的MakeSquare函数更改为以下内容:

public static Bitmap MakeSquare(byte[] data, int cameraID) {
    int width;
    int height;
    Matrix matrix = new Matrix();
    Camera.CameraInfo info = new Camera.CameraInfo();
    android.hardware.Camera.getCameraInfo(cameraID, info);
    // Convert ByteArray to Bitmap
    Bitmap bitPic = BitmapFactory.decodeByteArray(data, 0, data.length);
    width = bitPic.getWidth();
    height = bitPic.getHeight();

    // Perform matrix rotations/mirrors depending on camera that took the photo
    if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT)
    {
        float[] mirrorY = { -1, 0, 0, 0, 1, 0, 0, 0, 1};
        Matrix matrixMirrorY = new Matrix();
        matrixMirrorY.setValues(mirrorY);

        matrix.postConcat(matrixMirrorY);
    }

    matrix.postRotate(90);


    // Create new Bitmap out of the old one
    Bitmap bitPicFinal = Bitmap.createBitmap(bitPic, 0, 0, width, height,matrix, true);
    bitPic.recycle();
    int desWidth;
    int desHeight;
    desWidth = bitPicFinal.getWidth();
    desHeight = desWidth;
    Bitmap croppedBitmap = Bitmap.createBitmap(bitPicFinal, 0,bitPicFinal.getHeight() / 2 - bitPicFinal.getWidth() / 2,desWidth, desHeight);
    croppedBitmap = Bitmap.createScaledBitmap(croppedBitmap, 528, 528, true);
    return croppedBitmap;
}

这似乎起作用并解决了问题。虽然我不确定这是否是最佳方式,但我对此感到满意。现在我所要做的就是弄清楚当使用前置摄像头时为什么它不能采取适当的纵横比。


谢谢!你有关于这个解决方案在所有设备上运行情况的任何信息吗? - Marino
1
解决了我的前置摄像头图像旋转问题 (y) - Sheraz Ahmad Khilji
1
我无法看出这怎么可能会起作用。一些设备(例如 Nexus 6P)显示图像是倒置的,而其他设备(例如 Galaxy Tab Pro 8.4)则没有。您的代码总是翻转图像,这将在三星设备上出现问题,除非我误解了您的代码。 - CpnCrunch
太棒了,将图像旋转为纵向并且不翻转X轴,谢谢。 - DAVIDBALAS1

2
尝试使用这些链接:

http://developer.android.com/reference/android/hardware/Camera.html#setDisplayOrientation(int)

http://developer.android.com/reference/android/hardware/Camera.Parameters.html#setRotation(int)

具体来说,以下是setRotation链接中的一段话:
“如果应用程序想要旋转图片以匹配用户所看到的方向,则应使用OrientationEventListener和Camera.CameraInfo。OrientationEventListener的值相对于设备的自然方向。CameraInfo.orientation是相机方向与自然设备方向之间的角度。两者的总和是后置摄像头的旋转角度。前置摄像头的旋转角度为两者的差。请注意,前置摄像头的JPEG图片在预览显示中不会像镜像一样翻转。”
我原封不动地使用了这段代码。我的相机现在更好了,但仍需要一些细心呵护。我还没有前置功能。
祝你好运!

谢谢,我已经看过了它们并尝试按照他们的建议实现onOrientationChanged监听器,但我一直遇到崩溃问题。我已经编辑了我的帖子以展示我的代码。 - Valentin

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