将相机 SurfaceView 旋转为纵向

发布于 2024-12-05 05:59:13 字数 1774 浏览 0 评论 0原文

我查找了一些关于使用表面视图更改相机方向的帖子,但我从以下示例中获取了代码:

http://developer.android.com /resources/samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.html

提供尺寸的函数如下所示...

    private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
        final double ASPECT_TOLERANCE = 0.1;
        double targetRatio = (double) w / h;
        if (sizes == null) return null;

        Size optimalSize = null;
        double minDiff = Double.MAX_VALUE;

        int targetHeight = h;

        // Try to find an size match aspect ratio and size
        for (Size size : sizes) {
            double ratio = (double) size.width / size.height;
            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }

        // Cannot find the one match the aspect ratio, ignore the requirement
        if (optimalSize == null) {
            minDiff = Double.MAX_VALUE;
            for (Size size : sizes) {
                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }
        }
        return optimalSize;
    }

我的问题是,当我更改设备上,预览图片保持横向。我尝试设置相机的方向,但这导致了非常奇怪的结果。有谁知道我需要更改什么才能正确旋转?

I have looked up a few posts on changing the orientation of the camera with a surface view, but I have taken my code from the examples at:

http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.html

The function that provides the dimensions looks like this...

    private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
        final double ASPECT_TOLERANCE = 0.1;
        double targetRatio = (double) w / h;
        if (sizes == null) return null;

        Size optimalSize = null;
        double minDiff = Double.MAX_VALUE;

        int targetHeight = h;

        // Try to find an size match aspect ratio and size
        for (Size size : sizes) {
            double ratio = (double) size.width / size.height;
            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }

        // Cannot find the one match the aspect ratio, ignore the requirement
        if (optimalSize == null) {
            minDiff = Double.MAX_VALUE;
            for (Size size : sizes) {
                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }
        }
        return optimalSize;
    }

My problem is that when I change the orientation of the device, the preview picture stays landscape. I tried setting the orientation of the camera but this resulted in very strange results. Does anyone know what I need to change to have this rotate properly?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

筑梦 2024-12-12 05:59:13

正确调整相机预览方向的代码有点复杂,因为它必须考虑

  1. 传感器的相对方向和设备的“自然”方向(通常是手机的纵向,平板电脑的横向)
  2. 当前的 UI设备的方向(纵向、横向或各自的反向)
  3. 所涉及的摄像头是前置摄像头还是后置摄像头(因为前置预览流是水平镜像的)

Camera.setDisplayOrientation 有有关如何正确处理此问题的示例代码。我在这里重现它:

public static void setCameraDisplayOrientation(Activity activity,
     int cameraId, android.hardware.Camera camera) {

   android.hardware.Camera.CameraInfo info = 
       new android.hardware.Camera.CameraInfo();

   android.hardware.Camera.getCameraInfo(cameraId, info);

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

   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 (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
       result = (info.orientation + degrees) % 360;
       result = (360 - result) % 360;  // compensate the mirror
   } else {  // back-facing
       result = (info.orientation - degrees + 360) % 360;
   }
   camera.setDisplayOrientation(result);
}

在绘制 UI(onSurfaceChanged 将用作指示器)或设备 UI 旋转(onConfigurationChanged 将用作指示器)后调用此方法。

The code to correctly adjust the camera preview orientation is a bit complex, since it has to take into account

  1. The relative orientation of the sensor and the device's 'natural' orientation (which is portrait for phones, landscape for tablets, typically)
  2. The current UI orientation of the device (portrait, landscape or the reverse of each)
  3. Whether the camera in question is the front or the back camera (since the front preview stream is mirrored horizontally)

The documentation for Camera.setDisplayOrientation has sample code on how to deal with this correctly. I'm reproducing it here:

public static void setCameraDisplayOrientation(Activity activity,
     int cameraId, android.hardware.Camera camera) {

   android.hardware.Camera.CameraInfo info = 
       new android.hardware.Camera.CameraInfo();

   android.hardware.Camera.getCameraInfo(cameraId, info);

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

   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 (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
       result = (info.orientation + degrees) % 360;
       result = (360 - result) % 360;  // compensate the mirror
   } else {  // back-facing
       result = (info.orientation - degrees + 360) % 360;
   }
   camera.setDisplayOrientation(result);
}

Call this after your UI has been drawn (onSurfaceChanged would work as an indicator) or the device UI rotates (onConfigurationChanged would work as an indicator).

贱人配狗天长地久 2024-12-12 05:59:13

我能够通过将以下代码放入 onSurfaceChanged() 中来解决旋转问题:

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

    // stop preview before making changes
    try {
        mCamera.stopPreview();
    } catch (Exception e) {
        // ignore: tried to stop a non-existent preview
    }

    // make any resize, rotate or reformatting changes here
    if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {

        mCamera.setDisplayOrientation(90);

    } else {

        mCamera.setDisplayOrientation(0);

    }
    // start preview with new settings
    try {
        mCamera.setPreviewDisplay(mHolder);
        mCamera.startPreview();

    } catch (Exception e) {
        Log.d(TAG, "Error starting camera preview: " + e.getMessage());
    }

但这产生了另一个问题,或者更好地说,没有解决问题 - 虽然方向正确,但预览图像仍然只占用相同数量的景观景观所做的空间。我最终只是放弃并强制横向:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

在 onCreate() 中并设计了横向布局。祝你好运,我希望有人能解决这个次要问题!

I was able to solve the rotation problem by putting the following code in onSurfaceChanged():

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

    // stop preview before making changes
    try {
        mCamera.stopPreview();
    } catch (Exception e) {
        // ignore: tried to stop a non-existent preview
    }

    // make any resize, rotate or reformatting changes here
    if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {

        mCamera.setDisplayOrientation(90);

    } else {

        mCamera.setDisplayOrientation(0);

    }
    // start preview with new settings
    try {
        mCamera.setPreviewDisplay(mHolder);
        mCamera.startPreview();

    } catch (Exception e) {
        Log.d(TAG, "Error starting camera preview: " + e.getMessage());
    }

BUT this created another problem, or better put, didn't solve a problem-while oriented correctly, the preview image still only took up the same amount of space that the landscape view did. I ended up just giving up and forcing landscape orientation with:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

in onCreate() and designed my layout for landscape. Best of luck, and I hope someone has an answer for this secondary problem!

陪我终i 2024-12-12 05:59:13

试试这个,但我在 Samsung Galaxy Tab 上试过

public void surfaceCreated(SurfaceHolder holder)
{
   // The Surface has been created, acquire the camera and tell it where to draw.
   mCamera = Camera.open();

   Parameters params = mCamera.getParameters();

   if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE)
   {
    params.set("orientation", "portrait");
    mCamera.setDisplayOrientation(90);
   }

    try
      {
      mCamera.setPreviewDisplay(holder);
      }
      catch (IOException exception)
      {
        mCamera.release();
        mCamera = null;
      }

}

Try this out, but I tried in Samsung Galaxy Tab

public void surfaceCreated(SurfaceHolder holder)
{
   // The Surface has been created, acquire the camera and tell it where to draw.
   mCamera = Camera.open();

   Parameters params = mCamera.getParameters();

   if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE)
   {
    params.set("orientation", "portrait");
    mCamera.setDisplayOrientation(90);
   }

    try
      {
      mCamera.setPreviewDisplay(holder);
      }
      catch (IOException exception)
      {
        mCamera.release();
        mCamera = null;
      }

}
辞取 2024-12-12 05:59:13

我通过添加以下内容解决了这个问题:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

到 onCreate 事件。

I solved this issue by adding:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

To the onCreate event.

鸩远一方 2024-12-12 05:59:13

请尝试这个..

@Override
 public void surfaceChanged(SurfaceHolder holder,
                       int format, int width, int height)
{
// TODO Auto-generated method stub

if(previewing)
{
    camera.stopPreview();
    previewing = false;
}
 Camera.Parameters parameters = camera.getParameters();
      Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
   int or=cameraInfo.orientation;
     // You need to choose the most appropriate previewSize for your app
   // .... select one of previewSizes here
           /* parameters.setPreviewSize(previewSize.width, previewSize.height);*/
   if(display.getRotation() == Surface.ROTATION_0)
    {

    camera.setDisplayOrientation(90);
    or=90;
    }

    if(display.getRotation() == Surface.ROTATION_180)
    {
        camera.setDisplayOrientation(270);
    or=270;
    }
    if(display.getRotation() == Surface.ROTATION_270)
    {
        camera.setDisplayOrientation(180);
        or=180;
    }

  parameters.setRotation(or);

  camera.setParameters(parameters);
 try
{
        camera.setPreviewDisplay(cameraSurfaceHolder);
        camera.startPreview();
        previewing = true;
    }
    catch (IOException e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

Please try this..

@Override
 public void surfaceChanged(SurfaceHolder holder,
                       int format, int width, int height)
{
// TODO Auto-generated method stub

if(previewing)
{
    camera.stopPreview();
    previewing = false;
}
 Camera.Parameters parameters = camera.getParameters();
      Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
   int or=cameraInfo.orientation;
     // You need to choose the most appropriate previewSize for your app
   // .... select one of previewSizes here
           /* parameters.setPreviewSize(previewSize.width, previewSize.height);*/
   if(display.getRotation() == Surface.ROTATION_0)
    {

    camera.setDisplayOrientation(90);
    or=90;
    }

    if(display.getRotation() == Surface.ROTATION_180)
    {
        camera.setDisplayOrientation(270);
    or=270;
    }
    if(display.getRotation() == Surface.ROTATION_270)
    {
        camera.setDisplayOrientation(180);
        or=180;
    }

  parameters.setRotation(or);

  camera.setParameters(parameters);
 try
{
        camera.setPreviewDisplay(cameraSurfaceHolder);
        camera.startPreview();
        previewing = true;
    }
    catch (IOException e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
梦中的蝴蝶 2024-12-12 05:59:13

好吧,我这样做!

我已经在 surfaceCreated() 方法中以这种方式解决了这个问题,

 public void surfaceCreated(SurfaceHolder holder) {
    try {

        camera = Camera.open();
    } catch (RuntimeException e) {
        System.err.println(e);
        return;
    }
    Camera.Parameters param;
    param = camera.getParameters();
    if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE)
    {
        param.set("orientation", "portrait");
        setCameraDisplayOrientation(this,1,camera);
    }
    camera.setParameters(param);

    try {
        camera.setPreviewDisplay(surfaceHolder);
        camera.startPreview();
    } catch (Exception e) {
        System.err.println(e);
        return;
    }
}

在下面的 3 中添加此方法

 public static void setCameraDisplayOrientation(Activity activity,
                                               int cameraId, android.hardware.Camera camera) {

    android.hardware.Camera.CameraInfo info =
            new android.hardware.Camera.CameraInfo();

    android.hardware.Camera.getCameraInfo(cameraId, info);

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

    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 (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
        result = (info.orientation + degrees) % 360;
        result = (360 - result) % 360;  // compensate the mirror
    } else {  // back-facing
        result = (info.orientation - degrees + 360) % 360;
    }
    camera.setDisplayOrientation(result);
}

:确保您已添加相机权限以支持活动中的牛轧糖,在此活动调用不要在此活动中调用相机权限,因为 surfacecreated 调用为创建的活动,并且将等待您的许可才能打开相机

Well i Do this!

I have solved this issue in in this way in surfaceCreated() method

 public void surfaceCreated(SurfaceHolder holder) {
    try {

        camera = Camera.open();
    } catch (RuntimeException e) {
        System.err.println(e);
        return;
    }
    Camera.Parameters param;
    param = camera.getParameters();
    if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE)
    {
        param.set("orientation", "portrait");
        setCameraDisplayOrientation(this,1,camera);
    }
    camera.setParameters(param);

    try {
        camera.setPreviewDisplay(surfaceHolder);
        camera.startPreview();
    } catch (Exception e) {
        System.err.println(e);
        return;
    }
}

add this method below

 public static void setCameraDisplayOrientation(Activity activity,
                                               int cameraId, android.hardware.Camera camera) {

    android.hardware.Camera.CameraInfo info =
            new android.hardware.Camera.CameraInfo();

    android.hardware.Camera.getCameraInfo(cameraId, info);

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

    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 (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
        result = (info.orientation + degrees) % 360;
        result = (360 - result) % 360;  // compensate the mirror
    } else {  // back-facing
        result = (info.orientation - degrees + 360) % 360;
    }
    camera.setDisplayOrientation(result);
}

3: Make sure you have added camera permiison to support for nougat in a activity before this activity calling dont call permission for camera in this activity because surfacecreated call as the activity created, and your permission will be pending to open camera

逆夏时光 2024-12-12 05:59:13

仅添加此

mCamera.setDisplayOrientation(90);

Only add this

mCamera.setDisplayOrientation(90);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文