Android摄像头图像失真-SurfaceHolder-

Android摄像头图像失真-SurfaceHolder-,android,camera,surfaceholder,Android,Camera,Surfaceholder,我的相机表面有个奇怪的问题 我想在活动中显示摄像头的图像。 这一切在我的GalaxyS1(CyanogenMod-Android 4.4)上都非常有效 另一方面,在我的S3(也是CyanogenMod-Android4.4)上,它看起来很奇怪 没有标题栏的横向图像是正常的,但当我显示标题栏或将其转换为纵向模式时,它看起来扭曲了: ---编辑--- 谢谢亚历克斯·科恩的帮助。看来你是对的。portraid模式的预览现在运行良好。但从景观上看,它仍然是扭曲的。我检查了预览比例,看起来还可以。就我所

我的相机表面有个奇怪的问题

我想在活动中显示摄像头的图像。 这一切在我的GalaxyS1(CyanogenMod-Android 4.4)上都非常有效 另一方面,在我的S3(也是CyanogenMod-Android4.4)上,它看起来很奇怪

没有标题栏的横向图像是正常的,但当我显示标题栏或将其转换为纵向模式时,它看起来扭曲了:

---编辑---

谢谢亚历克斯·科恩的帮助。看来你是对的。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) {...}
private static final String TAG=CameraView.class.getSimpleName();
私人地勤人员地勤人员;
私人摄像机;
私有列表msupportedpreviews;
私人规模的mPreviewSize;
公共摄像师(活动){
超级(活动);
surfaceHolder=getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(surfaceHolder.SURFACE\u TYPE\u PUSH\u缓冲区);
camera=camera.open();
mSupportedPreviewSizes=camera.getParameters()
.getSupportedPreviewSizes();
设置摄像机方向(活动,0,摄像机);
}
@凌驾
公共无效表面更改(表面持有人,整数格式,整数w,整数h){
Camera.Parameters=Camera.getParameters();
parameters.setPreviewSize(mPreviewSize.width、mPreviewSize.height);
设置参数(参数);
camera.startPreview();
}
@凌驾
已创建的公共空白表面(表面持有人){
试一试{
摄像头。设置预览显示(支架);
}捕获(IOException异常){
相机。释放();
摄像机=零;
}
}
@凌驾
公共空间表面已覆盖(表面层arg0){
camera.stopPreview();
相机。释放();
摄像机=零;
}
@凌驾
测量时的保护空隙(内部宽度测量等级、内部高度测量等级){
最终整数宽度=resolveSize(getSuggestedMinimumWidth(),widthMeasureSpec);
最终整数高度=resolveSize(getSuggestedMinimumHeight(),heightMeasureSpec);
设置测量尺寸(宽度、高度);
if(mSupportedPreviewSizes!=null){
mPreviewSize=getOptimalPreviewSize(MSSupportedPreviewSize、宽度、高度);
}
}
私人相机。大小GetOptimizePreviewSize(列表大小,整数w,
int h){…}
公共静态无效设置和播放方向(活动,
int cameraId,摄像机){…}
---编辑---

我记录了onMeasure和surface change的值。他们似乎还行:

肖像:

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

测量:宽度:720高度:1134

景观:

表面更改:Witdh:1280高度:590

测量:宽度:1280高度:590

预览大小:宽度:704高度:576

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

数组中有8个元素:

960x720, 1280x720, 1184 x 666, 960x640, 704 x 576, 640x480, 352 x 288, 320 x 240

希望任何人都能帮忙

谢谢,
Tobias

问题的根源如下:

parameters.setPreviewSize(w, h);
surfaceChanged()
方法中。在Android中,不能将预览大小设置为任意值。只能使用返回的(w,h)对。否则,你就会陷入困境。实际上,许多设备只会在
camera.setParameters(parameters)
上引发一个运行时异常

不要求预览大小与用于显示它的曲面相同,例如,在640x480曲面上使用320x240预览是可以的。但是,如果预览和曲面具有不同的纵横比,则图像看起来会拉伸(请参见)。轻微的失真可能是可以容忍的,比如在800x400像素的屏幕上使用1280x720预览,但超过某个阈值时,您别无选择,只能使用部分屏幕,在预览上下留下边距


你可以找到开发者社区的想法:(这只是一个例子)。

哇,这似乎很有帮助。肖像模式就是这样工作的。不过,我还是遇到了一些问题(参见代码)。也许你知道为什么?谢谢你!请打印以记录您选择的大小以及
surfaceChanged()
onMeasure()回调中的
w,h
参数。我记录了这些值。他们看起来还不错,但也许你发现了什么。我猜它与标题栏有关,因为它似乎可以在全屏中找到。那么,您为1280x590选择的预览大小是多少?预览大小是:宽度:704高度:576-用于OnMeasure()中的函数;此外:如果我自动将预览设置为,比如说,320 x 240,它就可以按计划正常工作(只是拉伸)!