android camera中的预览图片变形的解决办法


之前处理相机模块的时候,遇到了一个问题,就是调用系统的camera的时候在拍照预览界面的时候看到的照片是变形的。不晓得大家有没有和我遇到一样的问题,后来发现是我的布局界面没有按对应的比例进行缩放导致的。后来参考了系统camera中的代码解决了这个问题,特此记录下来。每部手机中设置了好几组预览图片的尺寸、以及实际图片的尺寸。只有当预览图的尺寸比例和实际图片的比例相同的时候就不会出现变形的情况。下面一组数据是我测试中记录的一组数据:

02-09 19:00:40.831: D/tag(27507): pictureSizeValueString : 1280x960,1600x1200,2048x1536,2592x1456,2592x1936
02-09 19:00:40.831: D/tag(27507): previewSizeValueString : 176x144,320x240,352x288,640x480,720x480,720x576,848x480,1280x720

上面红色部分标记的都是具有相同比例的尺寸,都为4:3,而其他比例却不尽相同。故我们只要在初始化camera的时候给其设置好相同比例的预览图尺寸和实际图的尺寸,并且设置你的SurfaceView或者VideoView的尺寸比例相同就行了。但是要注意的是:魅族手机貌似取不到这些值。

复制代码
@Override
    public void surfaceCreated(SurfaceHolder holder) {
        try {
            //设置参数
            mCamera = Camera.open();
            //摄像头画面显示在Surface上
            mCamera.setPreviewDisplay(surfaceHolder);
            
            Parameters parameters = mCamera.getParameters();
        } catch (IOException e) {
            if (mCamera != null) mCamera.release(); 
            mCamera = null;
        }
        
        if (mCamera == null) {
            finish();
            return ;
        }
        updateCameraParameters();
        mCamera.startPreview();    
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        try {
            //摄像头画面显示在Surface上
            mCamera.setPreviewDisplay(surfaceHolder);
            updateCameraParameters();
            mCamera.startPreview();    
        } catch (IOException e) {
            if (mCamera != null) mCamera.release(); 
            mCamera = null;
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mCamera.stopPreview();
        //关闭预览
        mCamera.release();
        //释放资源
    }
复制代码



 

复制代码
private void updateCameraParameters() {
        if (mCamera != null) {
            Camera.Parameters p = mCamera.getParameters();
            
            long time = new Date().getTime();
            p.setGpsTimestamp(time);
            
            Size pictureSize = findBestPictureSize(p);
            p.setPictureSize(pictureSize.width, pictureSize.height);
            
            // Set the preview frame aspect ratio according to the picture size.
            Size size = p.getPictureSize();
            PreviewFrameLayout frameLayout = (PreviewFrameLayout) findViewById(R.id.frame_layout);
            frameLayout.setAspectRatio((double) size.width / size.height);
            
            Size previewSize = findBestPreviewSize(p);
            p.setPreviewSize(previewSize.width,previewSize.height);
            
            mCamera.setParameters(p);
            
            int supportPreviewWidth = previewSize.width;
            int supportPreviewHeight = previewSize.height;
            
            int srcWidth = getScreenWH().widthPixels;
            int srcHeight = getScreenWH().heightPixels;
            
            int width = Math.min(srcWidth, srcHeight);
            int height = width * supportPreviewWidth / supportPreviewHeight ;
           
            mSur.setLayoutParams(new FrameLayout.LayoutParams(height, width));//
        }
    }
    
    private Size findBestPictureSize(Camera.Parameters parameters) {
        int  diff = Integer.MIN_VALUE; 
        String pictureSizeValueString = parameters.get("picture-size-values");
         
         // saw this on Xperia
         if (pictureSizeValueString == null) {
             pictureSizeValueString = parameters.get("picture-size-value");
         }
         
         if(pictureSizeValueString == null) {
             return  mCamera.new Size(getScreenWH().widthPixels,getScreenWH().heightPixels);
         }
         
         Log.d("tag", "pictureSizeValueString : " + pictureSizeValueString);
         int bestX = 0;
         int bestY = 0;
        
        
         for(String pictureSizeString : COMMA_PATTERN.split(pictureSizeValueString))
         {
             pictureSizeString = pictureSizeString.trim();
             
             int dimPosition = pictureSizeString.indexOf('x');
             if(dimPosition == -1){
                 Log.e(TAG, "Bad pictureSizeString:"+pictureSizeString);
                 continue;
             }
             
             int newX = 0;
             int newY = 0;
             
             try{
                 newX = Integer.parseInt(pictureSizeString.substring(0, dimPosition));
                 newY = Integer.parseInt(pictureSizeString.substring(dimPosition+1));
             }catch(NumberFormatException e){
                 Log.e(TAG, "Bad pictureSizeString:"+pictureSizeString);
                 continue;
             }
            
             Point screenResolution = new Point (getScreenWH().widthPixels,getScreenWH().heightPixels);
             
             int newDiff = Math.abs(newX - screenResolution.x)+Math.abs(newY- screenResolution.y);
                 if(newDiff == diff)
                 {
                     bestX = newX;
                     bestY = newY;
                     break;
                 } else if(newDiff > diff){
                     if((3 * newX) == (4 * newY)) {
                         bestX = newX;
                         bestY = newY;
                         diff = newDiff;
                     }
                 }
             }
             
         if (bestX > 0 && bestY > 0) {
            return mCamera.new Size(bestX, bestY);
         }
        return null;
    }
    
    private Size findBestPreviewSize(Camera.Parameters parameters) {
        
         String previewSizeValueString = null;
         int diff = Integer.MAX_VALUE;
         previewSizeValueString = parameters.get("preview-size-values");
         
         if (previewSizeValueString == null) {
             previewSizeValueString = parameters.get("preview-size-value");
         }
        
         if(previewSizeValueString == null) {  // 有些手机例如m9获取不到支持的预览大小   就直接返回屏幕大小
             return  mCamera.new Size(getScreenWH().widthPixels,getScreenWH().heightPixels);
         }
         Log.d("tag", "previewSizeValueString : " + previewSizeValueString);
         int bestX = 0;
         int bestY = 0;
        
         for(String prewsizeString : COMMA_PATTERN.split(previewSizeValueString))
         {
             prewsizeString = prewsizeString.trim();
             
             int dimPosition = prewsizeString.indexOf('x');
             if(dimPosition == -1){
                 Log.e(TAG, "Bad prewsizeString:"+prewsizeString);
                 continue;
             }
             
             int newX = 0;
             int newY = 0;
             
             try{
                 newX = Integer.parseInt(prewsizeString.substring(0, dimPosition));
                 newY = Integer.parseInt(prewsizeString.substring(dimPosition+1));
             }catch(NumberFormatException e){
                 Log.e(TAG, "Bad prewsizeString:"+prewsizeString);
                 continue;
             }
            
             Point screenResolution = new Point (getScreenWH().widthPixels,getScreenWH().heightPixels);
             
             int newDiff = Math.abs(newX - screenResolution.x)+Math.abs(newY- screenResolution.y);
             
             if(newDiff == diff)
             {
                 bestX = newX;
                 bestY = newY;
                 break;
             } else if(newDiff < diff){
                 if((3 * newX) == (4 * newY)) {
                     bestX = newX;
                     bestY = newY;
                     diff = newDiff;
                 }
             }
         }
         if (bestX > 0 && bestY > 0) {
            return mCamera.new Size(bestX, bestY);
         }
        return null;
    }
    
     protected DisplayMetrics getScreenWH() {
        DisplayMetrics dMetrics = new DisplayMetrics();
        dMetrics = this.getResources().getDisplayMetrics();
        return dMetrics;
     }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值