Android-摄像头预览是横向的


123

我正在使用预览来显示相机在屏幕上看到的内容。

我可以使一切正常工作,创建曲面,设定曲面并显示曲面。

但是,它总是在人像模式下以不正确的90度角显示图片。

如图片所示:

替代文字

我知道,使用以下代码将使图片整洁:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

但是,我的活动中有预览,其中包含其他元素,因此以横向模式显示我的活动没有意义。(默认情况下禁用)

所以我想知道是否仍然可以更改预览的方向?并在“人像”模式下正确显示我的其余活动?

还是要旋转预览以使其正确显示?


Answers:


145

这个问题似乎是从某些硬件的错误开始的,请参见此处,但是可以通过使用API​​ 8中对mCamera.setDisplayOrientation(degrees)的调用来解决,因此,这就是我的实现方式:

public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {            
    if (isPreviewRunning) {
        mCamera.stopPreview();
    }

    Parameters parameters = mCamera.getParameters();
    Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();

    if(display.getRotation() == Surface.ROTATION_0) {
        parameters.setPreviewSize(height, width);                           
        mCamera.setDisplayOrientation(90);
    }

    if(display.getRotation() == Surface.ROTATION_90) {
        parameters.setPreviewSize(width, height);                           
    }

    if(display.getRotation() == Surface.ROTATION_180) {
        parameters.setPreviewSize(height, width);               
    }

    if(display.getRotation() == Surface.ROTATION_270) {
        parameters.setPreviewSize(width, height);
        mCamera.setDisplayOrientation(180);
    }

    mCamera.setParameters(parameters);
    previewCamera();                      
}

And the previewCamera method :

public void previewCamera() {        
    try {           
        mCamera.setPreviewDisplay(mSurfaceHolder);          
        mCamera.startPreview();
        isPreviewRunning = true;
    } catch(Exception e) {
        Log.d(APP_CLASS, "Cannot start preview", e);    
    }
}

这是在HTC Desire上进行的,我最初必须在每个旋转检查中都输入日志记录语句以说出旋转是什么,然后在设备上进行调试并在旋转设备时观看logCat输出。对于HTC Desire,“ 0”是您所期望的(纵向),“ 90度”将手机“逆时针”旋转90度(我以为它是顺时针方向)。在代码中,您会看到当手机处于90度或180度时,我不需要进行任何显示旋转-该设备似乎可以自行处理。只有一点不能正常工作:270度旋转是指您将设备顺时针旋转90度,并且显示屏旋转指示正常,但是如果您将设备逆时针旋转270度,则似乎无法正确补偿它。

PS注意在适当的旋转中宽度和高度的交换。


7
但是setDisplayOrientation(degree); 方法支持表格2.2,较低的版本呢?parameters.setRotation(90); parameters.set(“ orientation”,“ portrait”); 不工作。如果您有较低版本的任何解决方案,请帮助我。
维克拉姆

1
我在我的应用程序上实施了预览,该预览将始终以纵向模式显示。我一直将屏幕旋转90度,直到在HTC Desire C上对其进行测试之前,这似乎都可以在所有设备上使用。由于我现在不依靠该设备来进行此测试,因此,我想请您澄清一下此修复程序是否可以建议最终在HTC愿望上表现良好。谢谢!
argenkiwi 2012年

13
mCamera.setParameters(parameters);语句使我的应用程序崩溃,因为表面尺寸不是手机的有效预览尺寸(也许是因为我使状态栏保持可见?)。但是,我发现使用mCamera.setDisplayOrientation(90)then mCamera.setPreviewDisplay(mSurfaceHolder);而不设置参数也可以!
nicopico

3
使用switch语句会更清洁
Siavash

2
这不是假设预览在所有设备上都是横向的吗?因为它在某些设备上是侧向放置的,而在其他设备上是垂直放置的...。是否有办法检查设备的默认摄像头方向是否与手机的纵向一致?
Siavash

16

尝试设置显示方向。它解决了我的问题。

 mCamera.setDisplayOrientation(90);

5
在保存时会将肖像图像保存为横向图像。有什么解决方案吗?
阿肯莎(Akanksha Rathore)2013年

@Akanksha:此标志仅适用于预览显示。它不会更改返回的缓冲区的方向onPreviewFrame()onPictureTaken()
Alex Cohn 2015年

13
 public void surfaceCreated(SurfaceHolder holder) {
     mCamera = Camera.open();
     mCamera.setDisplayOrientation(90);
     try {
         mCamera.setPreviewDisplay(holder);
         mCamera.setPreviewCallback(new PreviewCallback() {

             @Override
             public void onPreviewFrame(byte[] data, Camera camera) {
             }
         });

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

试试这个代码


3
在保存时会将肖像图像保存为横向图像。有什么解决方案吗?
阿肯莎(Akanksha Rathore)2013年

@Akanksha可能与EXIF参数有关。
EpicPandaForce's

4

我的前置摄像头有问题(倒置问题)。然后,我使用了Android文档中记录的以下方法-

public void setCameraDisplayOrientation(Activity activity , int icameraId , Camera camera1s)
    {
        CameraInfo cameraInfo = new CameraInfo();

        Camera.getCameraInfo(icameraId, cameraInfo);

        int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();

        int degrees = 0; // k

        switch (rotation)
        {
        case Surface.ROTATION_0:
            degrees = 0;
            break;
        case Surface.ROTATION_90:
            degrees = 90;
            break;
        case Surface.ROTATION_180:
            degrees = 180;
            break;
        case Surface.ROTATION_270:
            degrees = 270;
            break;

        }

        int result;

        if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT)
        {
            // cameraType=CAMERATYPE.FRONT;

            result = (cameraInfo.orientation + degrees) % 360;
            result = (360 - result) % 360; // compensate the mirror

        }
        else
        { // back-facing

            result = (cameraInfo.orientation - degrees + 360) % 360;

        }
        // displayRotate=result;
        camera.setDisplayOrientation(result);


    }


@VinceFior如果他从官方文档中发帖,那有什么问题吗?
Ranjith Kumar

1
@RanjithKumar并不是特别的,我只是想感谢消息来源,并指出人们在这方面的情况。:)
VinceFior

3

我是在mCamera.setDisplayOrientation(90)的建议下完成的;但也旋转了位图,因为在某些情况下,其他方式在2.3.3版中对我不起作用。

为了旋转位图,我这样做:

Matrix matrix = new Matrix();
matrix.postRotate(90);
imageView1 = new ImageView(this);
Bitmap bitmap = BitmapFactory.decodeFile(files[i].getAbsolutePath());
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap , 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
Bitmap scaledBitmap = Bitmap.createScaledBitmap(rotatedBitmap, 80, 80, true);
imageView1.setImageBitmap(scaledBitmap);

0

我已将我的代码与本教程的代码进行了比较,最终解决的问题是将以下代码放入我的AndroidManifext.xml中:在<activity>标记中:

android:screenOrientation="landscape"
android:configChanges="keyboardHidden|orientation">

0
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    // If your preview can change or rotate, take care of those events here.
    // Make sure to stop the preview before resizing or reformatting it.

    if (mHolder.getSurface() == null) {
        // preview surface does not exist
        return;
    }

    try {
        mCamera.stopPreview();
    } catch (Exception e) {
        e.printStackTrace();
    }

    Camera.Parameters parameters = mCamera.getParameters();
    Display display = ((WindowManager) getContext().getSystemService(WINDOW_SERVICE)).getDefaultDisplay();

    if (display.getRotation() == Surface.ROTATION_0) {
        parameters.setPreviewSize(h, w);
        mCamera.setDisplayOrientation(90);
    }

    if (display.getRotation() == Surface.ROTATION_90) {
        parameters.setPreviewSize(w, h);
        mCamera.setDisplayOrientation(0);
    }

    if (display.getRotation() == Surface.ROTATION_180) {
        parameters.setPreviewSize(h, w);
        mCamera.setDisplayOrientation(270);
    }

    if (display.getRotation() == Surface.ROTATION_270) {
        parameters.setPreviewSize(w, h);
        mCamera.setDisplayOrientation(180);
    }

    previewCamera();
}

public void previewCamera() {
    try {
        mCamera.setPreviewDisplay(mHolder);
        mCamera.startPreview();
    } catch (Exception e) {
        //Log.d(APP_CLASS, "Cannot start preview", e);
        e.printStackTrace();
    }
}

0

我认为SENSOR_ORIENTATION值将解释用于旋转的值,而不是硬编码为90度

CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
        if (manager == null) {
            Log.i(TAG, "camera manager is null");
            return;
        }
        for (String id: manager.getCameraIdList()) {
            CameraCharacteristics characteristics = manager.getCameraCharacteristics(id);
            Integer orientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
            Log.i(TAG, "camera sensor orientation is " + orientation);
        }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.