关于Android camera2预览变形的坑
问题描述:
camera2使用后置摄像头预览时,预览画面被拉升。
分析:
获取camera前后摄像头id
private void cameraList(Context context) {cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);CameraCharacteristics characteristics = null;try {for (String cameraId : cameraManager.getCameraIdList()) {log("cameraId = " + cameraId);characteristics = cameraManager.getCameraCharacteristics(cameraId);if (characteristics.get(CameraCharacteristics.LENS_FACING) == CameraMetadata.LENS_FACING_BACK) {mBackCameraId = cameraId;} else if (characteristics.get(CameraCharacteristics.LENS_FACING) == CameraMetadata.LENS_FACING_FRONT) {mFontCameraId = cameraId;}}if (mBackCameraId != null) {mCameraId = mBackCameraId;} else if (mFontCameraId != null) {mCameraId = mFontCameraId;}} catch (CameraAccessException e) {e.printStackTrace();}if (characteristics != null) {StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);Size[] sizes = map.getOutputSizes(SurfaceTexture.class);if (sizes != null && sizes.length > 0) {
// for (Size size : mPreviewSize) {
// log("size = " + size.toString());
// }mPreviewSize = getBestSize(sizes);if (mPreviewSize != null) {log("bestSize = " + mPreviewSize.toString());}}}log("mCameraId = " + mCameraId);}
设置预览尺寸
public void setBestSize(SurfaceView surfaceView) {if (cameraManager == null) {return;}CameraCharacteristics characteristics = null;try {characteristics = cameraManager.getCameraCharacteristics(mCameraId);} catch (CameraAccessException e) {e.printStackTrace();}if (characteristics != null) {StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);Size[] sizes = map.getOutputSizes(SurfaceTexture.class);if (sizes != null && sizes.length > 0) {Point relPoint = new Point();context.getDisplay().getRealSize(relPoint);mPreviewSize = getBestSize(sizes);//, relPointif (mPreviewSize != null) {log("bestSize = " + mPreviewSize.toString());Point point = new Point();context.getDisplay().getRealSize(point);double ratio = (double) mPreviewSize.getHeight() / (double) mPreviewSize.getWidth();int phone_width = point.x;int phone_height = point.y;ViewGroup.LayoutParams layoutParams = surfaceView.getLayoutParams();if (((double) phone_width / (double) phone_height) < ratio) {layoutParams.width = (int) ((double) mPreviewSize.getHeight() / (double) mPreviewSize.getWidth() * phone_height);log("layoutParams.width = " + layoutParams.width);layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;} else {layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;layoutParams.height = (int) ((double) mPreviewSize.getWidth() / (double) mPreviewSize.getHeight() * phone_width);log("layoutParams.height = " + layoutParams.height);}surfaceView.setLayoutParams(layoutParams);}}}}
private Size getBestSize(Size[] outputSizes) {Point point = new Point();context.getDisplay().getRealSize(point);log("point = " + point);int phone_width = point.x;int phone_height = point.y;for (Size size : outputSizes) {double ratio = (double) size.getHeight() / (double) size.getWidth();
// double ratio = (double) size.getWidth() / (double) size.getHeight();int height = (int) (phone_width / ratio);if (height > phone_height) {} else {return size;}}return null;}
因为默认使用的后置摄像头预览,所以mCameraId = mBackCameraId,开始预览时预览画面被上下拉升。
修改了getBestSize方法,
public static Size getBestSize(Size[] outputSizes) {int minDiff = Integer.MAX_VALUE;float targetRatio = point.y * 1.0f / point.x;Size optimalSize = null;Point point = new Point();context.getDisplay().getRealSize(point);log("point = " + point);for (Size size : outputSizes) {log("size = " + size.toString());if (size.getWidth() > point.y && size.getHeight() > point.x) {float multipleW = size.getWidth() * 1.0f / point.y * 1.0f;float multipleH = size.getHeight() * 1.0f / point.x * 1.0f;if (multipleW == multipleH) {return size;}}if (size.getWidth() == point.y && size.getHeight() == point.x) {return size;}int diff = Math.abs((int) (targetRatio * size.getWidth()) - size.getHeight());log("diff = " + diff);if (diff < minDiff) {minDiff = diff;optimalSize = size;}}return optimalSize;}
预览画面没有变化,打印信息看着也没有问题
打印:
point = Point(720, 1280)
bestSize = 1920x1080
layoutParams.height = 1280
解决方案:
在测试只使用前置摄像头预览时,发现预览画面没有被拉升,查看打印信息
point = Point(720, 1280)
bestSize = 1600x1200
layoutParams.width = 960
bestSize返回不相同,后置相机和前置相机的Size[] sizes = map.getOutputSizes(SurfaceTexture.class);返回不一样。使用前置相机的Size在后置相机预览时也没有被拉升。