Camera.Parameters param = camera.getParameters();
param.setPreviewSize(width, height);java
width通常大於height,默認攝像頭是橫向,預覽時須要設置camera.setDisplayOrientation(90);android
常見的分辨率爲4:3,或者16:9,即640x480和1280x720git
Android6.0的源代碼中,預覽的大小和PictureSize有關,先看看系統如何設置Picture Sizegithub
代碼位置app
public static void initialCameraPictureSize( Context context, Parameters parameters) { // When launching the camera app first time, we will set the picture // size to the first one in the list defined in "arrays.xml" and is also // supported by the driver. List<Size> supported = parameters.getSupportedPictureSizes(); if (supported == null) return; for (String candidate : context.getResources().getStringArray( R.array.pref_camera_picturesize_entryvalues)) { if (setCameraPictureSize(candidate, supported, parameters)) { SharedPreferences.Editor editor = ComboPreferences .get(context).edit(); editor.putString(KEY_PICTURE_SIZE, candidate); editor.apply(); return; } } Log.e(TAG, "No supported picture size found"); }
讀取預先pref_camera_picturesize_entryvalues配置大小,而後在和設備支持的尺寸匹配,兩個相同的做爲pictureSize;並保存。ui
R.array.pref_camera_picturesize_entryvalues 中值爲this
<!-- When launching the camera app first time, we will set the picture size to the first one in the list that is also supported by the driver --> <string-array name="pref_camera_picturesize_entryvalues" translatable="false"> <item>3264x2448</item> <item>2592x1944</item> <item>2592x1936</item> <item>2560x1920</item> <item>2048x1536</item> <item>1600x1200</item> <item>1280x960</item> <item>1024x768</item> <item>640x480</item> <item>320x240</item> </string-array>
setCameraPictureSize 方法比較預先設置的之中是否有設置支持的大小相等的值google
public static boolean setCameraPictureSize( String candidate, List<Size> supported, Parameters parameters) { int index = candidate.indexOf('x'); if (index == NOT_FOUND) return false; int width = Integer.parseInt(candidate.substring(0, index)); int height = Integer.parseInt(candidate.substring(index + 1)); for (Size size : supported) { if (size.width == width && size.height == height) { parameters.setPictureSize(width, height); return true; } } return false; }
系統相機預覽大小的設置和picturesize有關。code
在startPreview中會調用updateCameraParametersPreference()方法orm
// Set the preview frame aspect ratio according to the picture size. Size size = mParameters.getPictureSize(); mPreviewPanel = findViewById(R.id.frame_layout); mPreviewFrameLayout = (PreviewFrameLayout) findViewById(R.id.frame); mPreviewFrameLayout.setAspectRatio((double) size.width / size.height); // Set a preview size that is closest to the viewfinder height and has // the right aspect ratio. List<Size> sizes = mParameters.getSupportedPreviewSizes(); Size optimalSize = Util.getOptimalPreviewSize(this, sizes, (double) size.width / size.height); Size original = mParameters.getPreviewSize(); if (!original.equals(optimalSize)) { mParameters.setPreviewSize(optimalSize.width, optimalSize.height); // Zoom related settings will be changed for different preview // sizes, so set and read the parameters to get lastest values mCameraDevice.setParameters(mParameters); mParameters = mCameraDevice.getParameters(); }
調用Util.getOptimalPreviewSize()方法獲取合適previewSize,
public static Size getOptimalPreviewSize(Activity currentActivity, List<Size> sizes, double targetRatio) { // Use a very small tolerance because we want an exact match. final double ASPECT_TOLERANCE = 0.001; if (sizes == null) return null; Size optimalSize = null; double minDiff = Double.MAX_VALUE; // Because of bugs of overlay and layout, we sometimes will try to // layout the viewfinder in the portrait orientation and thus get the // wrong size of preview surface. When we change the preview size, the // new overlay will be created before the old one closed, which causes // an exception. For now, just get the screen size. //獲取屏幕大小 Point point = getDefaultDisplaySize(currentActivity, new Point()); //相機默認橫屏,高度是二者中最小的一個 int targetHeight = Math.min(point.x, point.y); // Try to find an size match aspect ratio and size for (Size size : sizes) { double ratio = (double) size.width / size.height; //相機支持的比率和targetRatio相差太大時,繼續查找 if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue; //比率知足時,高度不能差太多 if (Math.abs(size.height - targetHeight) < minDiff) { optimalSize = size; minDiff = Math.abs(size.height - targetHeight); } } // Cannot find the one match the aspect ratio. This should not happen. // Ignore the requirement. if (optimalSize == null) { Log.w(TAG, "No preview size match the aspect ratio"); minDiff = Double.MAX_VALUE; for (Size size : sizes) { if (Math.abs(size.height - targetHeight) < minDiff) { optimalSize = size; minDiff = Math.abs(size.height - targetHeight); } } } return optimalSize; }
根據targetRatio,和實際屏幕大小來選擇SupportedPreviewSizes中合適的值。targetRatio我以爲也能夠使用屏幕比例。
initFromCameraParameters()方法會調用findBestPreviewSizeValue()方法獲取適合的大小;screenResolution爲屏幕大小
//private static final int MIN_PREVIEW_PIXELS = 320 * 240; // small screen //private static final int MAX_PREVIEW_PIXELS = 800 * 480; // large/HD screen private static Point findBestPreviewSizeValue(Camera.Parameters parameters, Point screenResolution, boolean portrait) { Point bestSize = null; int diff = Integer.MAX_VALUE; for (Camera.Size supportedPreviewSize : parameters.getSupportedPreviewSizes()) { int pixels = supportedPreviewSize.height * supportedPreviewSize.width; //預先設置大小 if (pixels < MIN_PREVIEW_PIXELS || pixels > MAX_PREVIEW_PIXELS) { continue; } int supportedWidth = portrait ? supportedPreviewSize.height : supportedPreviewSize.width; int supportedHeight = portrait ? supportedPreviewSize.width : supportedPreviewSize.height; //不太理解爲啥要交叉相乘,總之是比較差值 int newDiff = Math.abs(screenResolution.x * supportedHeight - supportedWidth * screenResolution.y); if (newDiff == 0) { bestSize = new Point(supportedWidth, supportedHeight); break; } //更新最小差值 if (newDiff < diff) { bestSize = new Point(supportedWidth, supportedHeight); diff = newDiff; } } //若是還沒找到,就使用預覽值 if (bestSize == null) { Camera.Size defaultSize = parameters.getPreviewSize(); bestSize = new Point(defaultSize.width, defaultSize.height); } return bestSize; }
zxing中是根據實際屏幕值,根設備支持的尺寸交叉相乘,獲取差值最小設爲最合適的值,若是沒有使用預覽值。
zxing使用方法比較簡單些。