我們在Android中經常會使用SurfaceView編寫自定義的攝像頭,可是有的時候會經常會出現圖像的變形,我們就會很郁悶的問這到底是為什么呢?其實這個最根本的原因是SurfaceView和PreViewSize的尺寸不是同一個比率。
所謂PreViewSize就是在預覽的時候幀數據的尺寸,SurfaceView是用來預覽Camera的視圖,它的尺寸也就是Screen全屏時候的大小。還有一個重要尺寸的是PictureSize,這個是拍照后圖片的尺寸,就是所保存的結果圖片的大小。
所以解決剛剛問題就是調用Camera的takePicture方法之前設置一下Camera的PictureSize和PreviewSize兩個參數,分別調用的方法是setPictureSize和setPreviewSize。
然后實際的PictureSize和PreviewSize可通過如下步驟得到的:
首先是得到該手機可以適配的一系列尺寸
List<Size> previewSizes = params.getSupportedPreviewSizes();
List<Size> pictureSizes = params.getSupportedPictureSizes();
然后得到自己的屏幕的尺寸
public static float getScreenRate(Context context){ Point P = getScreenMetrics(context); float H = P.y; float W = P.x; return (W/H); }
最后根據自己的尺寸大小,從適配的尺寸當中取一些屬於自己規格的尺寸
public Size getPropPreviewSize(List<Camera.Size> list, float th, int minWidth){ Collections.sort(list, sizeComparator); int i = 0; for(Size s:list){ if((s.width >= minWidth) && equalRate(s, th)){ Log.i(TAG, "PreviewSize:w = " + s.width + ",h = " + s.height); break; } i++; } if(i == list.size()){ i = 0;//如果沒找到,就選最小的size } return list.get(i); }
得到PreViewSize后,同理得到PictureSize
public Size getPropPictureSize(List<Camera.Size> list, float th, int minWidth){ Collections.sort(list, sizeComparator); int i = 0; for(Size s:list){ if((s.width >= minWidth) && equalRate(s, th)){ Log.i(TAG, "PictureSize : w = " + s.width + ",h = " + s.height); break; } i++; } if(i == list.size()){ i = 0;//如果沒找到,就選最小的size } return list.get(i); }
設置尺寸
mParams = mCamera.getParameters(); //設置PictureSize Size pictureSize = getPropPictureSize(mParams.getSupportedPictureSizes(),previewRate, 1280); mParams.setPictureSize(pictureSize.width, pictureSize.height); //設置PreviewSize Size previewSize = getPropPreviewSize(mParams.getSupportedPreviewSizes(), previewRate, 1280); mParams.setPreviewSize(previewSize.width, previewSize.height);
這樣子關於在Android上調用Camera捕捉圖像后在SurfaceView上變形顯示的問題基本上就解決了!