2.1、构造器
构造器包含了初始化域以及添加上述回调的过程。
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
这里需要说明mSupportedPreviewSizes,由于摄像头支持的预览尺寸由Camera本身的参数决定,因此需要首先获取其所支持的预览尺寸。
2.2、预览尺寸的设置
从Google官方的Camera示例程序中可以看出,选择预览尺寸的标准是(1)摄像头支持的预览尺寸的宽高比与SurfaceView的宽高比的绝对差值小于0.1;(2)在(1)获得的尺寸中,选取与SurfaceView的高的差值最小的。通过代码对这两个标准进行了实现,这里贴一下官方的代码:
public Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) w / h;
if (sizes == null) {
return null;
}
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;
}
在加载预览画面时,需要考虑Camera支持的尺寸(getSupportedPreviewSizes)和加载预览画面的SurfaceView的尺寸(layout_width/layout_height),在预览阶段,两者之间的关系直接影响清晰度及图像拉伸。对于Camera的尺寸,由于设备的硬件差异,不同设备支持的尺寸存在差异,但在默认情况(orientation=landscape)下,其width>height。以HTC609d为例,Camera支持的分辨率为1280*720(16:9)……640*480(4:3)……480*320(3:2)等十多种,而其屏幕的分辨率为960*540(16:9)。因此,很容易得到以下结论:(1)当Camera预览尺寸小于SurfaceView尺寸较多时,预览画面就不清晰;(2)Camera预览尺寸宽高比与SurfaceView宽高比相差较大时,预览画面就会拉伸。










