【问题标题】:Android - Camera preview is sidewaysAndroid - 相机预览是横向的
【发布时间】:2011-04-19 23:02:10
【问题描述】:

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

我可以让一切正常工作,创建表面,设置表面并显示表面。

但在纵向模式下,它总是以错误的 90 度角显示图片。

如图片中:

我知道使用下面的代码会使图片变得清晰:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

但是,我在一个包含其他元素的 Activity 中有预览,并且我的 Activity 以横向模式显示是没有意义的。 (默认关闭)

所以我想知道是否可以只更改预览的方向?并让我的 Activity 的其余部分以纵向模式正确显示?

或者无论如何要旋转预览以使其正确显示?

【问题讨论】:

标签: android camera orientation preview portrait


【解决方案1】:

我认为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);
        }

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    【解决方案3】:

    这个问题一开始似乎是某些硬件 see here 的错误,但可以通过使用 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 度,它似乎无法正确补偿。

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

    【讨论】:

    • 但是 setDisplayOrientation(degree);方法支持form 2.2,低版本呢??参数.setRotation(90); parameters.set("方向", "肖像");不工作。如果您对较低版本有任何解决方案,请帮助我。
    • 我在我的应用上实现了一个预览,它始终以纵向模式显示。我总是将屏幕旋转 90 度,这似乎适用于每台设备,直到我们在 HTC Desire C 上对其进行测试。由于我现在不指望设备来测试这个,我希望你澄清这是否能解决你建议终于在 HTC 的愿望上运作良好。谢谢!
    • mCamera.setParameters(parameters); 语句使我的应用程序崩溃,因为表面尺寸不是我手机的有效预览尺寸(可能是因为我保持状态栏可见?)。但是,我发现在不设置参数的情况下使用mCamera.setDisplayOrientation(90) 然后mCamera.setPreviewDisplay(mSurfaceHolder); 也可以!
    • 使用 switch 语句会更干净
    • 这不是假设预览在所有设备上都是横向的吗?因为它在某些设备上是横向的,而在其他设备上是直立的……有没有办法检查设备的默认摄像头方向是否与手机的纵向一致?
    【解决方案4】:
    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();
        }
    }
    

    【讨论】:

      【解决方案5】:

      我是根据 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);
      

      【讨论】:

        【解决方案6】:

        我已将我的代码与教程一进行了比较,最终修复它的是将以下代码放入我的 AndroidManifext.xml: 在<activity> 标签中:

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

        【讨论】:

          【解决方案7】:

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

           mCamera.setDisplayOrientation(90);
          

          【讨论】:

          • 在保存时将纵向图像保存为横向。任何解决方案?
          • @Akanksha:此标志仅适用于预览显示。它不会改变onPreviewFrame()onPictureTaken() 中返回的缓冲区的方向
          【解决方案8】:
           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();
               }
          }
          

          试试这个代码

          【讨论】:

          • 在保存时将纵向图像保存为横向。任何解决方案?
          • @Akanksha 这可能与 EXIF 参数有关。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-06-17
          • 2016-05-05
          • 2013-07-22
          • 2010-10-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多