一、Camera 简化思路
-
在 Camera 的开发中,其实我们通常只关注打开相机、图像预览和关闭相机,其他的步骤我们不应该花费太多的精力
-
为此,应该提供一个工具类,它有处理相机的一些基本工具方法,包括获取摄像头 ID、选择最优预览尺寸以及打印相机参数信息
二、Camera 工具类
- CameraIdResult.java
java
public class CameraIdResult {
private int qzCameraId = -1; // 前置摄像头 id
private int hzCameraId = -1; // 后置摄像头 id
public CameraIdResult() {
}
public CameraIdResult(int qzCameraId, int hzCameraId) {
this.qzCameraId = qzCameraId;
this.hzCameraId = hzCameraId;
}
public int getQzCameraId() {
return qzCameraId;
}
public void setQzCameraId(int qzCameraId) {
this.qzCameraId = qzCameraId;
}
public int getHzCameraId() {
return hzCameraId;
}
public void setHzCameraId(int hzCameraId) {
this.hzCameraId = hzCameraId;
}
}
- MyCameraTool.java
java
public class MyCameraTool {
public static final String TAG = MyCameraTool.class.getSimpleName();
/**
* 得到摄像头 Id 对象
*
* @return 摄像头 Id 对象,它有前置摄像头 Id 和后置摄像头 Id
*/
public static CameraIdResult getCameraIdResult() {
CameraIdResult cameraIdResult = new CameraIdResult();
int numberOfCameras = Camera.getNumberOfCameras();
Log.i(TAG, "------------------------------ 摄像头个数:" + numberOfCameras);
for (int cameraId = 0; cameraId < numberOfCameras; cameraId++) {
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, cameraInfo);
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
Log.i(TAG, "------------------------------ 前置摄像头,cameraId 为:" + cameraId);
cameraIdResult.setQzCameraId(cameraId);
}
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
Log.i(TAG, "------------------------------ 后置摄像头,cameraId 为:" + cameraId);
cameraIdResult.setHzCameraId(cameraId);
} else {
Log.i(TAG, "------------------------------ 其他摄像头,cameraId 为:" + cameraId);
}
}
return cameraIdResult;
}
/**
* 根据 SurfaceView 的尺寸和相机支持的预览尺寸来选择最优的预览尺寸
*
* @param sizes 相机支持的预览尺寸列表
* @param w SurfaceView 的宽度
* @param h SurfaceView 的高度
* @return 最优的预览尺寸,如果没有合适的尺寸则返回 null
*/
public static Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
if (sizes == null) return null;
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) h / w;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
// 遍历所有支持的预览尺寸
for (Camera.Size size : sizes) {
// 检查宽高比是否接近目标宽高比
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
// 计算当前尺寸与目标尺寸的宽度差异
// 如果差异小于当前最小差异,则更新最优尺寸和最小差异
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
// 如果找不到接近目标宽高比的尺寸,则选择最接近目标高度的尺寸
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
/**
* 打印相机参数信息
*
* @param parameters 相机参数对象
*/
public static void showParameters(Camera.Parameters parameters) {
Camera.Size previewSize = parameters.getPreviewSize();
Log.i(TAG, "============================== getPreviewSize");
Log.i(TAG, "---------- " + previewSize.width + " - " + previewSize.height);
List<Camera.Size> supportedPreviewSizes = parameters.getSupportedPreviewSizes();
Log.i(TAG, "============================== supportedPreviewSizes");
Log.i(TAG, "============================== supportedPreviewSizes size: " + supportedPreviewSizes.size());
for (Camera.Size supportedPreviewSize : supportedPreviewSizes) {
Log.i(TAG, "---------- " + supportedPreviewSize.width + " - " + supportedPreviewSize.height);
}
Camera.Size pictureSize = parameters.getPictureSize();
Log.i(TAG, "============================== getPictureSize");
Log.i(TAG, "---------- " + pictureSize.width + " - " + pictureSize.height);
List<Camera.Size> supportedPictureSizes = parameters.getSupportedPictureSizes();
Log.i(TAG, "============================== getSupportedPictureSizes");
Log.i(TAG, "============================== getSupportedPictureSizes: " + supportedPictureSizes.size());
for (Camera.Size supportedPictureSize : supportedPictureSizes) {
Log.i(TAG, "---------- " + supportedPictureSize.width + " - " + supportedPictureSize.height);
}
String focusMode = parameters.getFocusMode();
Log.i(TAG, "============================== getFocusMode");
Log.i(TAG,"---------- " + focusMode);
String whiteBalance = parameters.getWhiteBalance();
Log.i(TAG, "============================== getWhiteBalance");
Log.i(TAG,"---------- " + whiteBalance);
int exposureCompensation = parameters.getExposureCompensation();
Log.i(TAG, "============================== getExposureCompensation");
Log.i(TAG,"---------- " + exposureCompensation);
String flashMode = parameters.getFlashMode();
Log.i(TAG, "============================== getFlashMode");
Log.i(TAG,"---------- " + flashMode);
}
}
三、Camera 工具类解析
1、获取取摄像头 ID
-
该方法用于获取取摄像头 ID,它会返回一个 cameraIdResult 对象
-
cameraIdResult 对象有两个属性为 qzCameraId 和 hzCameraId,分别代表前置摄像头 ID 和后置摄像头 ID,如果 qzCameraId 或 hzCameraId 的值为 -1,代表没有获取到
java
public static CameraIdResult getCameraIdResult() {
CameraIdResult cameraIdResult = new CameraIdResult();
int numberOfCameras = Camera.getNumberOfCameras();
Log.i(TAG, "------------------------------ 摄像头个数:" + numberOfCameras);
for (int cameraId = 0; cameraId < numberOfCameras; cameraId++) {
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, cameraInfo);
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
Log.i(TAG, "------------------------------ 前置摄像头,cameraId 为:" + cameraId);
cameraIdResult.setQzCameraId(cameraId);
}
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
Log.i(TAG, "------------------------------ 后置摄像头,cameraId 为:" + cameraId);
cameraIdResult.setHzCameraId(cameraId);
} else {
Log.i(TAG, "------------------------------ 其他摄像头,cameraId 为:" + cameraId);
}
}
return cameraIdResult;
}
2、选择最优预览图像尺寸
- 该方法用于选择最优预览图像尺寸,设置最优预览图像尺寸,能保证在预览图像时(例如,SurfaceView)图像不被拉伸
java
public static Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
if (sizes == null) return null;
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) h / w;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
// 遍历所有支持的预览尺寸
for (Camera.Size size : sizes) {
// 检查宽高比是否接近目标宽高比
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
// 计算当前尺寸与目标尺寸的宽度差异
// 如果差异小于当前最小差异,则更新最优尺寸和最小差异
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
// 如果找不到接近目标宽高比的尺寸,则选择最接近目标高度的尺寸
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
3、打印相机参数信息
- 该方法用于打印相机参数信息,用于了解设备,并根据业务做更合适的设置
-
例如,根据 supportedPreviewSizes 可以对预览图像的大小做更合适的设置(SurfaceView、setPreviewSize 方法)
-
再例如,根据 getSupportedPictureSizes 可以对拍照时图片的大小做更合适的设置(setPictureSize 方法)
java
public static void showParameters(Camera.Parameters parameters) {
Camera.Size previewSize = parameters.getPreviewSize();
Log.i(TAG, "============================== getPreviewSize");
Log.i(TAG, "---------- " + previewSize.width + " - " + previewSize.height);
List<Camera.Size> supportedPreviewSizes = parameters.getSupportedPreviewSizes();
Log.i(TAG, "============================== supportedPreviewSizes");
Log.i(TAG, "============================== supportedPreviewSizes size: " + supportedPreviewSizes.size());
for (Camera.Size supportedPreviewSize : supportedPreviewSizes) {
Log.i(TAG, "---------- " + supportedPreviewSize.width + " - " + supportedPreviewSize.height);
}
Camera.Size pictureSize = parameters.getPictureSize();
Log.i(TAG, "============================== getPictureSize");
Log.i(TAG, "---------- " + pictureSize.width + " - " + pictureSize.height);
List<Camera.Size> supportedPictureSizes = parameters.getSupportedPictureSizes();
Log.i(TAG, "============================== getSupportedPictureSizes");
Log.i(TAG, "============================== getSupportedPictureSizes: " + supportedPictureSizes.size());
for (Camera.Size supportedPictureSize : supportedPictureSizes) {
Log.i(TAG, "---------- " + supportedPictureSize.width + " - " + supportedPictureSize.height);
}
String focusMode = parameters.getFocusMode();
Log.i(TAG, "============================== getFocusMode");
Log.i(TAG,"---------- " + focusMode);
String whiteBalance = parameters.getWhiteBalance();
Log.i(TAG, "============================== getWhiteBalance");
Log.i(TAG,"---------- " + whiteBalance);
int exposureCompensation = parameters.getExposureCompensation();
Log.i(TAG, "============================== getExposureCompensation");
Log.i(TAG,"---------- " + exposureCompensation);
String flashMode = parameters.getFlashMode();
Log.i(TAG, "============================== getFlashMode");
Log.i(TAG,"---------- " + flashMode);
}