Android 如何修复相机方向

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20064793/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 02:16:21  来源:igfitidea点击:

Android how to fix camera orientation

androidandroid-activitycameraorientation

提问by CENT1PEDE

Notice how the view of the camera (NOT THE CAPTURED IMAGE) was flipped to left (image above), the orientation of the Activityis correct, but the camera view is messed up, please help me guys :) thank you.

注意相机的视图(不是捕获的图像)是如何向左翻转的(上图),方向Activity是正确的,但是相机视图被弄乱了,请帮帮我:)谢谢。

Here is the XML layout file:

这是 XML 布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center|top"
            android:orientation="vertical" >

            <SurfaceView
                android:id="@+id/camerapreview"
                android:layout_margin="10dp"
                android:layout_width="300dp"
                android:layout_height="300dp" />
        </LinearLayout>
    </LinearLayout>

</LinearLayout>

And here is the code for the activity:

这是活动的代码:

public class CustomCameraActivity extends Activity implements SurfaceHolder.Callback {

    Camera camera;
    SurfaceView surfaceView;
    SurfaceHolder surfaceHolder;
    boolean previewing = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.camera);

        surfaceView = (SurfaceView)findViewById(R.id.camerapreview);
        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(this);

    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        if(previewing){
            camera.stopPreview();
            previewing = false;
        }

        if (camera != null){
            try {
                camera.setPreviewDisplay(surfaceHolder);
                camera.startPreview();
                previewing = true;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        camera = Camera.open();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        camera.stopPreview();
        camera.release();
        camera = null;
        previewing = false;
    }
}

回答by CENT1PEDE

I found the solution here. Answer by @Ed Jellard.

我在这里找到了解决方案。@Ed Jellard 的回答。

i just have to add camera.setDisplayOrientation(90);on surfaceCreated(SurfaceHolder holder)method, now the display is on the right angle.

我只需要添加camera.setDisplayOrientation(90);surfaceCreated(SurfaceHolder holder)的方法,现在显示的是在直角。

see the happy T-REX :)

看到快乐的 T-REX :)

回答by Louis GRIGNON

This problem was solved a long time ago but I encountered some difficulties to put all pieces together so here is my final solution, I hope this will help others :

这个问题很久以前就解决了,但是我在将所有部分放在一起时遇到了一些困难,所以这是我的最终解决方案,我希望这会对其他人有所帮助:

public void startPreview() {
        try {
            Log.i(TAG, "starting preview: " + started);

            // ....
            Camera.CameraInfo camInfo = new Camera.CameraInfo();
            Camera.getCameraInfo(cameraIndex, camInfo);
            int cameraRotationOffset = camInfo.orientation;
            // ...

            Camera.Parameters parameters = camera.getParameters();
            List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();
            Camera.Size previewSize = null;
            float closestRatio = Float.MAX_VALUE;

            int targetPreviewWidth = isLandscape() ? getWidth() : getHeight();
            int targetPreviewHeight = isLandscape() ? getHeight() : getWidth();
            float targetRatio = targetPreviewWidth / (float) targetPreviewHeight;

            Log.v(TAG, "target size: " + targetPreviewWidth + " / " + targetPreviewHeight + " ratio:" + targetRatio);
            for (Camera.Size candidateSize : previewSizes) {
                float whRatio = candidateSize.width / (float) candidateSize.height;
                if (previewSize == null || Math.abs(targetRatio - whRatio) < Math.abs(targetRatio - closestRatio)) {
                    closestRatio = whRatio;
                    previewSize = candidateSize;
                }
            }

            int rotation = getWindowManager().getDefaultDisplay().getRotation();
            int degrees = 0;
            switch (rotation) {
            case Surface.ROTATION_0:
                degrees = 0;
                break; // Natural orientation
            case Surface.ROTATION_90:
                degrees = 90;
                break; // Landscape left
            case Surface.ROTATION_180:
                degrees = 180;
                break;// Upside down
            case Surface.ROTATION_270:
                degrees = 270;
                break;// Landscape right
            }
            int displayRotation;
            if (isFrontFacingCam) {
                displayRotation = (cameraRotationOffset + degrees) % 360;
                displayRotation = (360 - displayRotation) % 360; // compensate
                                                                    // the
                                                                    // mirror
            } else { // back-facing
                displayRotation = (cameraRotationOffset - degrees + 360) % 360;
            }

            Log.v(TAG, "rotation cam / phone = displayRotation: " + cameraRotationOffset + " / " + degrees + " = "
                    + displayRotation);

            this.camera.setDisplayOrientation(displayRotation);

            int rotate;
            if (isFrontFacingCam) {
                rotate = (360 + cameraRotationOffset + degrees) % 360;
            } else {
                rotate = (360 + cameraRotationOffset - degrees) % 360;
            }

            Log.v(TAG, "screenshot rotation: " + cameraRotationOffset + " / " + degrees + " = " + rotate);

            Log.v(TAG, "preview size: " + previewSize.width + " / " + previewSize.height);
            parameters.setPreviewSize(previewSize.width, previewSize.height);
            parameters.setRotation(rotate);
            camera.setParameters(parameters);
            camera.setPreviewDisplay(mHolder);
            camera.startPreview();

            Log.d(TAG, "preview started");

            started = true;
        } catch (IOException e) {
            Log.d(TAG, "Error setting camera preview: " + e.getMessage());
        }
    }

回答by Faizan Mubasher

There is a property in class Camera.CameraInfonamed as orientation. It returns the integer. You can get the current orientation and then changed accordingly.

类中有一个Camera.CameraInfo名为的属性orientation。它返回整数。您可以获取当前方向,然后进行相应更改。

See this answerfor handling orientation and CameraInfoclass.

请参阅此答案以了解处理方向和CameraInfo类。

I am sure this will help you.

我相信这会对你有所帮助。

回答by Rahul Gupta

Camera rotates automatically when you rotate your phone, However if you want the image captured by camera or from gallery to be in the right orientation, use this :-

旋转手机时相机会自动旋转,但是如果您希望相机或图库拍摄的图像处于正确的方向,请使用:-

public void rotate(String filePath){
              Bitmap cameraBitmap = null;
            BitmapFactory.Options bmOptions = new BitmapFactory.Options();
            bmOptions.inJustDecodeBounds = false;
            bmOptions.inPurgeable = true;
            bmOptions.inBitmap = cameraBitmap; 
            bmOptions.inMutable = true; 

        cameraBitmap = BitmapFactory.decodeFile(filePath,bmOptions); 
        // Your image file path
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            cameraBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);


        ExifInterface exif = new ExifInterface(filePath);
        float rotation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);  
        System.out.println(rotation);

        float rotationInDegrees = exifToDegrees(rotation);
        System.out.println(rotationInDegrees);

        Matrix matrix = new Matrix();
        matrix.postRotate(rotationInDegrees);

        Bitmap rotatedBitmap = Bitmap.createBitmap(cameraBitmap , 0, 0, cameraBitmap.getWidth(), cameraBitmap.getHeight(), matrix, true);
        FileOutputStream fos=new FileOutputStream(filePath);
        rotatedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
        fos.write(bos.toByteArray());
        cameraBitmap.recycle();
        System.gc();
        fos.flush();
        fos.close();
}

private static float exifToDegrees(float exifOrientation) {        
    if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) { return 90; } 
    else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) {  return 180; } 
    else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) {  return 270; }            
    return 0;    
}