Camera是什么
Camera官方说明The Camera class is used toset image capture settings, start/stop preview, snap pictures, and retrieveframes for encoding for video. This class is a client for the Camera service,which manages the actual camera hardware.
大概意思是Camera是一个用来设置图片获取选项,开启/关闭预览,连续拍照,获取视频解码每一帧,对于管理实际摄像硬件的Camer service来说它相当于一个客户端。
Camera应用场景
项目开发中经常会遇到拍照或录像的需求,有两种实现方式一种是调用系统相机,另一种是使用系统Camera类和surfaceView来实现自定义Camera。
Camera使用
1 Menifest添加权限
<!--允许使用相机-->
<uses-permission android:name="android.permission.CAMERA"/>
<!--允许使用外部存储-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!--允许使用闪光灯-->
<uses-permission android:name="android.permission.FLASHLIGHT"/>
<!--使用相机特性-->
<uses-feature android:name="android.hardware.camera"/>
<uses-feature android:name="android.hardware.camera.autofocus"/>
2.打开相机
判断是否有相机
/**
* check if the device has a camera
* @return
*/
private boolean checkCameraHardWare() {
if(getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
return true;
}
return false;
}
调用Camera的open方法获取实例
/**
* a safe way to get an instance ofCamera Object
* @return
*/private CameragetCameraInst() {
Camera cameraInst = null;
try {
cameraInst = cameraInst.open();
} catch(Exception e) {
e.printStackTrace();
}
returncameraInst;
}
3.初始化
a 设置拍摄角度
b 设置相机参数,预览大小,闪光灯开关,缩放比例。
c 设置预览要使用的surfaceholder
d 打开预览
Camera.Parameters parameters = mCamera.getParameters();
// ......设置Camera参数
mCamera.setParameters(parameters);
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
4 使用相机
获取图片
a. 调用takePictrue,会触发一个异步的图片获取,以及多个回调。此方法会导致预览关闭,若想继续预览在获取图片后再次调用startPreview
参数说明
shutter call back 当图片被获取到的时候会被回调,可以用来播放一个声音让用户知道图片已经被获取到。
PictureCallBack raw 当图片的原始数据可用时会被回调
PictureCallBack postView 当发生缩放时会被回调,并不是所有设备都支持。
PictureCallBack jpeg 当被压缩的图片可用时,会被回调
mCameraInstance.takePicture(null, null, new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
// 在这里处理获取到的图片,data可直接转化为bitmap或图片文件
}
});
b另外获取视频的示例这里暂时不做过多介绍,可参考官方文档https://developer.android.com/guide/topics/media/camera.html
5关闭预览,释放相机资源。
注意
a。注意:一定要设置预览大小,否则图片会变形。设置预览尺寸,首先获取设备支持的预览尺寸列表,找到与屏幕分辨率差值最小的并设置。
List<Camera.Size>supportedPreviewSizes = parameters.getSupportedPreviewSizes();
WindowManager windowManager =(WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
int screenW = windowManager.getDefaultDisplay().getWidth();
int screenH =windowManager.getDefaultDisplay().getHeight();
Log.d("hezd","supportscreen size:width="+screenW+",height="+screenH);
int diff = Integer.MAX_VALUE;
Camera.Size beseSize = null;
for(Camera.Size size : supportedPreviewSizes){
Log.d("hezd","supportsize:width="+size.width+",height="+size.height);
int height= Math.abs(screenH-size.height);
int width= Math.abs(size.width-screenW);
int currentDiff= width+height;
if(currentDiff==0||currentDiff<diff){
beseSize = size;
diff= currentDiff;
}
}
if(beseSize!=null) {
parameters.setPreviewSize(beseSize.width,beseSize.height);
}
B 要截取的预览区域非全屏的情况获取图片
这种情况还是比较麻烦的,如果直接使用扫描框的坐标去截取获取的图片是不正确,因为这时获取的图片是尺寸不一定是当前扫描框父窗体的的尺寸。我在这里的解决办法是先将图片缩小到同当前父窗体相同尺寸,在根据扫描框坐标去截取。
Matrix matrix = new Matrix();
matrix.postRotate(90);
matrix.postScale(difW,difH);
Bitmap rotateBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix,true);
if(bitmap!=null){
bitmap.recycle();
}
ByteArrayOutputStream bos = new ByteArrayOutputStream();
rotateBitmap.compress(Bitmap.CompressFormat.JPEG,100,bos);
try {
BitmapRegionDecoder regionDecoder =BitmapRegionDecoder.newInstance(bos.toByteArray(),0,bos.toByteArray().length,false);
Rectrect = new Rect(mScaLeft,mScanTop,mScanWidth,mScanHeight);
BitmapregionBitmap = regionDecoder.decodeRegion(rect, options);
mShowPicIv.setVisibility(View.VISIBLE);
mShowPicIv.setImageBitmap(rotateBitmap);
mPicIv.setImageBitmap(regionBitmap);
} catch(IOException e) {
e.printStackTrace();
}
另外还想到一个办法,没有尝试,有兴趣的同学可以尝试一下,就是去设置相机图片尺寸,然后再去截取。
身份证扫描
在应用中需要对身份证扫描获取信息的场景很多,参考很多ocr相关资料和项目后,编写了一个示例工程,在文章最后附上地址。
代码下载
身份证扫描项目地址