【问题标题】:Rotating a Camera SurfaceView to portrait将相机 SurfaceView 旋转为纵向
【发布时间】:2011-11-19 07:15:43
【问题描述】:

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

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;
    }

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

【问题讨论】:

    标签: android camera rotation


    【解决方案1】:

    只添加这个

    mCamera.setDisplayOrientation(90);
    

    【讨论】:

    • 这会增加什么新东西吗?
    【解决方案2】:

    好吧,我这样做!

    我已经在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;
        }
    }
    

    在下面添加这个方法

     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:请确保您在此活动调用之前已添加相机权限以支持牛轧糖在此活动中调用不要在此活动中调用相机权限,因为在创建活动时表面创建调用,并且您的权限将等待打开相机

    【讨论】:

    • 您好,您访问此答案的最后一个朋友,我可以帮助您更友好地在这里输入消息
    【解决方案3】:

    请试试这个..

    @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();
        }
    }
    

    【讨论】:

      【解决方案4】:

      试试这个,但我在三星 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;
            }
      
      }
      

      【讨论】:

      • 我目前没有工作环境来测试它(我修改得有点太多了),但是一旦我启动并运行它,我会试试这个
      • params.set("orientation", "portrait"); mCamera.setDisplayOrientation(90); 定位就像宝石!
      • 谢谢@VIGNESH.SRINIVASAGAN,你救了我的朋友!!!
      【解决方案5】:

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

      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 将用作指示器)后调用此函数。

      【讨论】:

      • 如何在onSurfaceChanged中设置这个方法??
      • 参数中的camera id是什么,请解释方法的参数
      • cameraId = 0 后置摄像头,cameraId = 1 前置摄像头。此方法不适用于所有设备。
      【解决方案6】:

      我通过添加解决了这个问题:

      setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
      

      到 onCreate 事件。

      【讨论】:

        【解决方案7】:

        我可以通过将以下代码放入 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() 中并为横向设计了我的布局。祝你好运,我希望有人能解答这个次要问题!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-01-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多