Android Camera开发分辨率相关问题总结

相机相关的开发时,发现并解决了一些问题,并将其记录于下以便以后查看。

问题
  1. 设置了previewSize和pictureSize,但是通过打Log看出当时设置的时候分辨率是改变了的,然而正是拍照的时候分辨率又变回系统默认的了,在不同的机子上默认的分辨率不同。
  2. setParameters failed 问题
  3. 我的华为的默认的previewSize是最高的,然而pictureSize又是最低的,导致预览的图片十分清晰,而拍出的照片十分小且模糊。
  4. 同样使用默认分辨率,在一些机子上会出现预览变形的情况。
解决
1. 设置预览分辨率和图片分辨率
Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewSize(width, height);   parameters.setPictureSize(width, height);

设置完后一定要记得:

camera.setParameters(parameters);`

我就是设置完之后没有将parameters又设置回去故分辨率设置了完全没用,拍照时又变回去了。也是太粗心了。
然而设置完后新的问题又出现了:

2. setParameters failed问题解决
java.lang.RuntimeException: setParameters failed
 at android.hardware.Camera.native_setParameters(Native Method)
 at android.hardware.Camera.setParameters(Camera.java:1834)

经过我查资料,发现出现这样的问题是因为设置的parameter不符合规范。
也就是说previewSize和pictureSize不是随便想设什么就设什么的,要看那款手机的摄像头具体支持些什么参数,如果摄像头不支持,那么设置就会出错。

通过如下方法得到可以设置的分辨率参数:

    public void parameters(Camera camera) {
        List<Camera.Size> pictureSizes = camera.getParameters().getSupportedPictureSizes();
        List<Camera.Size> previewSizes = camera.getParameters().getSupportedPreviewSizes();
        Camera.Size psize;
        for (int i = 0; i < pictureSizes.size(); i++) {
            psize = pictureSizes.get(i);
           Log.i("pictureSize",psize.width+" x "+psize.height);
        }
        for (int i = 0; i < previewSizes.size(); i++) {
            psize = previewSizes.get(i);
            Log.i("previewSize",psize.width+" x "+psize.height);
        }
    }

通过观察输出结果发现:

  1. previewSize和pictureSize大多不一样,只有少数几个参数既支持previewSize又支持pictureSize.
  2. width一般大于height,应该是因为默认的摄像头是横向的,在我们预览的时候也要设置
camera.setDisplayOrientation(90);

将摄像头转过来,否则看到的就是横着的画面。所以我们设置previewSize和pictureSize时也要注意width一般大于height,所以如果像这样

camera.setPerviewSize(screenWidth,screenHeight);

单纯的将获取到的屏幕宽高设置进分辨率是不一定会成功的。一是可能不支持,二是可能参数设反了。

除了分辨率大小设置错误之外,还有其他的parameter设置不符规范的话也是会报错的,在设置的时候还要仔细检查。

3. 分辨率设置

对于这第三个问题,主要是预览和图片分辨率不匹配,因为预览和图片采用的是不同的分辨率,如果默认预览分辨率很高而图片分辨率很低的话就会出现预览清晰而照片模糊的情况。

对于这种情况,可以根据上面得到的可以设置的分辨率参数将预览和图片的分辨率设置成一样的。

还可以直接将预览的图像保存为图片,这样看到的图片就和预览的时候是一样的了。
首先需要实现Camera.PreviewCallback接口并重写其方法onPreviewFrame(byte[] data,Camera camera)以获得预览数据。然后在开启预览camera.startPreview()后camera.setPreviewCallback(this)。这样每次在开始预览后都能得到预览数据。定义一个全局变量mData使其赋值为onPreviewFrame(byte[] data,Camera camera)中的data,然后在再将该预览数据保存为照片。由于现在市面上销售的Android设备所配备的相机,它们获取的预览数据都是YUV420SP规格的字节数组,这种数组是不能直接转换成Bitmap对象的。所以需要先将获取的预览数据即YUV420SP字节数组转换成RGB565的int型数组,再将其转换成Bitmap对象进行存储。如果预览的分辨率较高的话那么用预览数据保存的图像也较为清晰。

    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        mData = data;
    }

具体的保存预览图像的代码网上有很多,我就不多赘述了。

4、预览变形解决

还是分辨率的问题,一般手机屏幕分辨率为16:9,而可能默认的预览分辨率是4:3的,然而我们在设置布局文件的时候设置的预览界面SurfaceView宽高均为match_parent,让预览界面充满屏幕,所以自然就会出现预览变形的情况。

我解决这个问题的方法是:

1.修改布局文件:

     <SurfaceView
        android:id="@+id/surface_2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"/>

2.获取屏幕分辨率和默认的预览分辨率(或者自己已经设置过的预览分辨率),并计算分辨率的宽高比,如果是16:9则就让SurfaceView的高也充满屏幕,否则就通过屏幕的分辨率和预览分辨率计算比例,相应的调整SurfaceView的高。这样就可以解决预览变形的问题。

先在Activity的onCreate中获取屏幕分辨率:

     WindowManager windowManager = getWindowManager();
     Display display = windowManager.getDefaultDisplay();
     DisplayMetrics metrics = new DisplayMetrics();
     //获取屏幕的宽和高
     display.getMetrics(metrics);
     screenWidth = metrics.widthPixels;
     screenHeight = metrics.heightPixels;

计算预览分辨率的宽高比:

    public String getSurfaceViewSize(int width, int height) {
        if (equalRate(width, height, 1.33f)) {
            return "4:3";
        } else {
            return "16:9";
        }
    }

    public boolean equalRate(int width, int height, float rate) {
        float r = (float)width /(float) height;
        if (Math.abs(r - rate) <= 0.2) {
            return true;
        } else {
            return false;
        }
    }

根据分辨率设置SurfaceView的大小:

    /**
     * 根据分辨率设置预览SurfaceView的大小以防止变形
     *
     * @param surfaceSize
     */
    private void setSurfaceViewSize(String surfaceSize) {
        ViewGroup.LayoutParams params = surfaceView.getLayoutParams();
        if (surfaceSize.equals("16:9")) {
            params.height = ViewGroup.LayoutParams.MATCH_PARENT;
        } else if (surfaceSize.equals("4:3")) {
            params.height = 4 * screenWidth / 3;
        }
        surfaceView.setLayoutParams(params);
    }

这样基本就不会变形了,还有些手机可能既不是16:9也不是4:3 的屏幕分辨率,都可以通过计算比例适当缩放使其不变形。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值