一、Camera API说明
1、Camera:操作和管理相机资源,支持相机资源切换,设置预览和拍摄尺寸,设置光圈、曝光等相关参数
2、SurfaceView:用于绘制相机预览图像,提供实时预览的图像
3、SurfaceHolder:用于控制Surface的一个抽象接口,它可以控制Surface的尺寸、格式与像素等,并可以监视Surface的变化
4、SurfaceHolder.Callback:用于监听Surface状态变化的接口,SurfaceHolder.Callback接口里定义了三个函数:
(1)、surfaceCreated(SurfaceHolder holder); 当Surface第一次创建的时候调用,可以在这个方法里调用camera.open()、camera.setPreviewDisplay()来实现打开相机以及连接Camera与Surface
等操作
(2)、surfaceChanged(SurfaceHolder holder, int format, int width, int height); 当Surface的size、format等发生变化的时候调用,可以在这个方法里调用camera.startPreview()开启预览。
(3)、surfaceDestroyed(SurfaceHolder holder); 当Surface被销毁的时候调用,可以在这个方法里调用camera.stopPreview(),camera.release()等方法来实现结束预览以及释放
(4)、闪光灯配置参数,可以通过Parameters.getFlashMode()接口获取
Camera.Parameters.FLASH_MODE_AUTO 自动模式,当光线较暗时自动打开闪光灯;
Camera.Parameters.FLASH_MODE_OFF 关闭闪光灯;
Camera.Parameters.FLASH_MODE_ON 拍照时闪光灯;
Camera.Parameters.FLASH_MODE_RED_EYE 闪光灯参数,防红眼模式
(5)、对焦模式配置参数,可以通过Parameters.getFocusMode()接口获取
Camera.Parameters.FOCUS_MODE_AUTO 自动对焦模式,摄影小白专用模式;
Camera.Parameters.FOCUS_MODE_FIXED 固定焦距模式,拍摄老司机模式;
Camera.Parameters.FOCUS_MODE_EDOF 景深模式,文艺女青年最喜欢的模式;
Camera.Parameters.FOCUS_MODE_INFINITY 远景模式,拍风景大场面的模式;
Camera.Parameters.FOCUS_MODE_MACRO 微焦模式,拍摄小花小草小蚂蚁专用模式
(5)、场景模式配置参数,可以通过Parameters.getSceneMode()接口获取
Camera.Parameters.SCENE_MODE_BARCODE 扫描条码场景,NextQRCode项目会判断并设置为这个场景;
Camera.Parameters.SCENE_MODE_ACTION 动作场景,就是抓拍跑得飞快的运动员、汽车等场景用的;
Camera.Parameters.SCENE_MODE_AUTO 自动选择场景;
Camera.Parameters.SCENE_MODE_HDR 高动态对比度场景,通常用于拍摄晚霞等明暗分明的照片;
Camera.Parameters.SCENE_MODE_NIGHT 夜间场景;
二、Camera1使用,具体流程如下:
1、调用Camera.open(),打开相机,默认为后置,可以根据摄像头ID来指定打开前置还是后置
2、调用Camera.getParameters()得到一个Camera.Parameters对象
3、使用步骤2得到的Camera.Parameters对象,对拍照参数进行设置
4、调用Camera.setPreviewDispaly(SurfaceHolder holder),指定使用哪个SurfaceView来显示预览图片
5、调用Camera.startPreview()方法开始预览取景
调用Camera.takePicture()方法进行拍照
6、拍照结束后,调用Camera.stopPreview()结束取景预览,之后再replease()方法释放资源
三、代码实现如下
1、在AndroidManifest.xml添加权限
<uses-permission android:name="android.permission.CAMERA"/>
2、写布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent">
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:text="拍照"
android:layout_height="wrap_content" />
<SurfaceView
android:id="@+id/surface_view_camera2_activity"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
android:id="@+id/iv_show_camera2_activity"
android:layout_width="180dp"
android:layout_height="320dp"
android:visibility="gone"
android:layout_centerInParent="true"
android:scaleType="centerCrop" />
</LinearLayout>
3、代码实现
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static String TAG = "wq:camera";
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
private Camera mCamera;
private ImageView iv_show;
private int viewWidth, viewHeight;//mSurfaceView的宽和高
private int numberOfCameras;
private int faceBackCameraId;
private int faceBackCameraOrientation;
private int faceFrontCameraId;
private int faceFrontCameraOrientation;
private int displayRotation;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e(TAG,"onCreate()");
initView();
}
/**
* 初始化控件
*/
private void initView() {
iv_show = (ImageView) findViewById(R.id.iv_show_camera2_activity);
//mSurfaceView
mSurfaceView = (SurfaceView) findViewById(R.id.surface_view_camera2_activity);
mSurfaceHolder = mSurfaceView.getHolder();
// mSurfaceView 不需要自己的缓冲区
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// mSurfaceView添加回调
mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) { //SurfaceView创建
Log.e(TAG,"surfaceCreated()");
// 初始化Camera
initCamera();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.e(TAG,"surfaceChanged()");
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) { //SurfaceView销毁
Log.e(TAG,"surfaceDestroyed()");
// 释放Camera资源
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
}
}
});
//设置点击监听
//mSurfaceView.setOnClickListener(this);
Button button = (Button)findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mCamera == null) return;
//自动对焦后拍照
mCamera.autoFocus(autoFocusCallback);
}
});
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (mSurfaceView != null) {
viewWidth = mSurfaceView.getWidth();
viewHeight = mSurfaceView.getHeight();
Log.e(TAG,"onWindowFocusChanged()"+"=viewWidth=="+viewWidth+"=viewHeight="+viewHeight);
}
}
/**
* SurfaceHolder 回调接口方法
*/
private void initCamera() {
//添加权限
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
== PackageManager.PERMISSION_GRANTED) {
System.out.println("ok");
}else {
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CAMERA},1);
}
//有多少个摄像头
numberOfCameras = Camera.getNumberOfCameras();
Log.e(TAG,"initCamera()"+"=numberOfCameras=="+numberOfCameras);
for (int i = 0; i < numberOfCameras; ++i) {
final Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
Camera.getCameraInfo(i, cameraInfo);
//后置摄像头
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
faceBackCameraId = i;
faceBackCameraOrientation = cameraInfo.orientation;
}
//前置摄像头
else if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
faceFrontCameraId = i;
faceFrontCameraOrientation = cameraInfo.orientation;
}
}
Log.e(TAG,"initCamera()"+"=faceBackCameraId=="+faceFrontCameraId);
Log.e(TAG,"initCamera()"+"=faceBackCameraOrientation=="+faceFrontCameraId);
Log.e(TAG,"initCamera()"+"=faceFrontCameraId=="+faceFrontCameraId);
Log.e(TAG,"initCamera()"+"=faceFrontCameraOrientation=="+faceFrontCameraId);
mCamera = Camera.open(0);//默认开启后置,0代表后置摄像头,1代表前置摄像头
//根据手握手机的方向来设置摄像头的方向
final Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
Camera.getCameraInfo(faceFrontCameraId, cameraInfo);
int cameraRotationOffset = cameraInfo.orientation;
final int rotation = ((WindowManager) this.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break; // Natural orientation
case Surface.ROTATION_90:
degrees = 90;
break; // Landscape left
case Surface.ROTATION_180:
degrees = 180;
break;// Upside down
case Surface.ROTATION_270:
degrees = 270;
break;// Landscape right
}
//根据前置与后置摄像头的不同,设置预览方向,否则会发生预览图像倒过来的情况。
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
displayRotation = (cameraRotationOffset + degrees) % 360;
displayRotation = (360 - displayRotation) % 360; // compensate
} else {
displayRotation = (cameraRotationOffset - degrees + 360) % 360;
}
mCamera.setDisplayOrientation(displayRotation);//摄像头进行旋转90°
if (mCamera != null) {
try {
Camera.Parameters parameters = mCamera.getParameters();
//设置预览照片的大小
parameters.setPreviewFpsRange(viewWidth, viewHeight);
//设置相机预览照片帧数
parameters.setPreviewFpsRange(4, 10);
//设置图片格式
parameters.setPictureFormat(ImageFormat.JPEG);
//设置图片的质量
parameters.set("jpeg-quality", 90);
//设置照片的大小
parameters.setPictureSize(viewWidth, viewHeight);
//通过SurfaceView显示预览
mCamera.setPreviewDisplay(mSurfaceHolder);
//开始预览
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 点击回调方法
*/
@Override
public void onClick(View v) {
if (mCamera == null) return;
//自动对焦后拍照
mCamera.autoFocus(autoFocusCallback);
}
/**
* 自动对焦 对焦成功后 就进行拍照
*/
Camera.AutoFocusCallback autoFocusCallback = new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
Log.e(TAG,"onAutoFocus()"+"=success=="+success);
if (success) {//对焦成功
camera.takePicture(new Camera.ShutterCallback() {//按下快门
@Override
public void onShutter() {
//按下快门瞬间的操作
}
}, new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {//是否保存原始图片的信息
}
}, pictureCallback);
}
}
};
/**
* 获取图片
*/
Camera.PictureCallback pictureCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
Log.e(TAG,"onPictureTaken()==data=="+data.length);
final Bitmap resource = BitmapFactory.decodeByteArray(data, 0, data.length);
if (resource == null) {
Toast.makeText(MainActivity.this, "拍照失败", Toast.LENGTH_SHORT).show();
}
final Matrix matrix = new Matrix();
matrix.setRotate(45);
final Bitmap bitmap = Bitmap.createBitmap(resource, 0, 0, resource.getWidth(), resource.getHeight(), matrix, true);
if (bitmap != null && iv_show != null && iv_show.getVisibility() == View.GONE) {
mCamera.stopPreview();
iv_show.setVisibility(View.VISIBLE);
mSurfaceView.setVisibility(View.GONE);
Toast.makeText(MainActivity.this, "拍照", Toast.LENGTH_SHORT).show();
iv_show.setImageBitmap(bitmap);
}
}
};
}
4、执行流程如下
1、进入应用日志
12-15 18:25:47.091 22287-22287/wq.com.camerademo E/wq:camera: onCreate()
12-15 18:25:47.154 22287-22287/wq.com.camerademo E/wq:camera: surfaceCreated()
12-15 18:25:47.157 22287-22287/wq.com.camerademo E/wq:camera: initCamera()=numberOfCameras==2
12-15 18:25:47.160 22287-22287/wq.com.camerademo E/wq:camera: initCamera()=faceBackCameraId==1
initCamera()=faceBackCameraOrientation==1
initCamera()=faceFrontCameraId==1
initCamera()=faceFrontCameraOrientation==1
12-15 18:25:47.423 22287-22287/wq.com.camerademo E/wq:camera: surfaceChanged()
12-15 18:25:47.463 22287-22287/wq.com.camerademo E/wq:camera: onWindowFocusChanged()=viewWidth==1080=viewHeight=1542
2、按back键返回退出的日志
12-15 17:58:00.281 20473-20473/wq.com.camerademo E/wq:camera: onWindowFocusChanged()=viewWidth==1080=viewHeight=1542
12-15 17:58:00.404 20473-20473/wq.com.camerademo E/wq:camera: surfaceDestroyed()
3、点击拍照的日志
12-15 17:58:29.108 20473-20473/wq.com.camerademo E/wq:camera: onAutoFocus()=success==true
12-15 17:58:29.672 20473-20473/wq.com.camerademo E/wq:camera: onPictureTaken()==data==1430619
12-15 17:58:31.057 20473-20473/wq.com.camerademo E/wq:camera: surfaceDestroyed()
5、效果图如下