Android相机图像失真 - SurfaceHolder -

时间:2014-03-22 14:33:44

标签: android camera surfaceholder

我的Camera-SurfaceHolder有一个奇怪的问题。

我想在我的活动中显示相机的图像。 这一切都在我的GalaxyS1上有很大的作用(CyanogenMod - Android 4.4) 另一方面,在我的S3(也是CyanogenMod - Android 4.4)上看起来很奇怪。

没有标题栏的风景图片没问题,但是当我显示标题栏或将其转换为肖像模式时,它看起来很扭曲:

enter image description here

---编辑---

谢谢Alex Cohn的帮助。看起来你是对的。 portraid模式的预览现在运行良好。但它仍然看起来在景观视图上扭曲了。我检查了预览比例,看起来没问题。据我所知,我也正确设置了预览尺寸。那有什么问题呢?

以下是当前代码:

    private static final String TAG = CameraView.class.getSimpleName();

      private SurfaceHolder surfaceHolder;
      private Camera camera;
      private List<Size> mSupportedPreviewSizes;
      private Size mPreviewSize;

      public CameraView(Activity activity) {
        super(activity);
        surfaceHolder = getHolder();
        surfaceHolder.addCallback(this);
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        camera = Camera.open();
        mSupportedPreviewSizes = camera.getParameters()
                .getSupportedPreviewSizes();
        setCameraDisplayOrientation(activity, 0, camera);
      }

      @Override
      public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        Camera.Parameters parameters = camera.getParameters();
        parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
        camera.setParameters(parameters);
        camera.startPreview();
      }

      @Override
      public void surfaceCreated(SurfaceHolder holder) {
       try {
         camera.setPreviewDisplay(holder);
       } catch (IOException exception) {
             camera.release();
             camera = null;
       }
      }

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

   @Override
   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
    final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
                setMeasuredDimension(width, height);

    if (mSupportedPreviewSizes != null) {
        mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
    }
  }

  private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w,
                int h) {...}

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

---编辑---

我记录了onMeasure和surface Changed的值。他们似乎没问题:

  

肖像:

     

表面变化:Witdh:720身高:1134

     

onMeasure:宽度:720高度:1134

     

风景:

     

表面变化:Witdh:1280身高:590

     

onMeasure:宽度:1280高度:590

     

预览尺寸:宽度:704高度:576

我得到以下可能的预览尺寸。

数组中有8个元素:

960 x 720, 1280 x 720, 1184 x 666, 960 x 640, 704 x 576 , 640 x 480, 352 x 288, 320 x 240

希望任何人都可以提供帮助!

谢谢,  托拜厄斯

1 个答案:

答案 0 :(得分:2)

您的问题来源如下:

parameters.setPreviewSize(w, h);
surfaceChanged()方法中的

。您无法在Android中将预览大小设置为任意值。您应该只使用 Parameters.getSupportedPreviewSizes() 返回的(w,h)对。否则,您会遇到 appearing to succeed is a valid form of undefined behavior 情况。实际上,许多设备只会在camera.setParameters(parameters)上引发 RuntimeException ,但您的开发平台选择表现不同。

不要求预览尺寸与用于显示它的表面相同,例如在640x480表面上使用320x240预览是可以的。但是,如果您的预览和曲面具有不同的宽高比,则图像看起来会拉伸(请参阅http://i.stack.imgur.com/VFwes.jpg)。轻微失真可能是可以忍受的,例如在800x400像素场景上使用1280x720预览,但是超过特定阈值,您别无选择,只能使用部分屏幕,在预览的上方和下方留下边距。

您可以找到开发者社区提出的建议:use getOptimalPreviewSize() for given width, hight(这只是一个例子)。