之前处理相机模块的时候,遇到了一个问题,就是调用系统的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; }