一步一步解析google camera2 demo(四)

目录:
一、Camera2关键类解析
二、打开相机
三、预览
四、拍照

拍照

1、给拍照按钮注册事件,onViewCreated()方法是Fragment加载布局(即onCreateView())完成后响应的。

public void onViewCreated(final View view, Bundle savedInstanceState) {
	view.findViewById(R.id.picture).setOnClickListener(this);
	view.findViewById(R.id.info).setOnClickListener(this);
	mTextureView = (AutoFitTextureView) view.findViewById(R.id.texture);
}

R.id.picture就是拍照按钮,将当前Fragment对象作为事件响应对象。

2、实现检测拍照按钮被点击的响应函数以及下发capture request。

public void onClick(View view) {
	switch (view.getId()) {
		case R.id.picture: {
			takePicture();
			break;
		}
		case R.id.info: {
			Activity activity = getActivity();
			if (null != activity) {
				new AlertDialog.Builder(activity)
						.setMessage(R.string.intro_message)
						.setPositiveButton(android.R.string.ok, null)
						.show();
			}
			break;
		}
	}
}

private void takePicture() {
	lockFocus();
}

private void lockFocus() {
	try {
		// This is how to tell the camera to lock focus.
		mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
				CameraMetadata.CONTROL_AF_TRIGGER_START);
		// Tell #mCaptureCallback to wait for the lock.
		mState = STATE_WAITING_LOCK;
		mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback,
				mBackgroundHandler);
	} catch (CameraAccessException e) {
		e.printStackTrace();
	}
}

可以看到,在lockFocus()函数中,首先通过mPreviewRequestBuilder.build()创建一个capture request,这个request用于通知对应的camera设备需要对焦,然后通过session的capture()方法,将request submit到框架。

3、在capture()方法的响应,提供的mCaptureCallback,如下:

private CameraCaptureSession.CaptureCallback mCaptureCallback
		= new CameraCaptureSession.CaptureCallback() {

	private void process(CaptureResult result) {
		switch (mState) {
			case STATE_PREVIEW: {
				// We have nothing to do when the camera preview is working normally.
				break;
			}
			case STATE_WAITING_LOCK: {
				Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
				if (afState == null) {
					captureStillPicture();
				} else if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState ||
						CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) {
					// CONTROL_AE_STATE can be null on some devices
					Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
					if (aeState == null || aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
						mState = STATE_PICTURE_TAKEN;
						captureStillPicture();
					} else {
						runPrecaptureSequence();
					}
				}
				break;
			}
			case STATE_WAITING_PRECAPTURE: {
				// CONTROL_AE_STATE can be null on some devices
				Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
				if (aeState == null ||
						aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE ||
						aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED) {
					mState = STATE_WAITING_NON_PRECAPTURE;
				}
				break;
			}
			case STATE_WAITING_NON_PRECAPTURE: {
				// CONTROL_AE_STATE can be null on some devices
				Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
				if (aeState == null || aeState != CaptureResult.CONTROL_AE_STATE_PRECAPTURE) {
					mState = STATE_PICTURE_TAKEN;
					captureStillPicture();
				}
				break;
			}
		}
	}

	@Override
	public void onCaptureProgressed(@NonNull CameraCaptureSession session,
									@NonNull CaptureRequest request,
									@NonNull CaptureResult partialResult) {
		process(partialResult);
	}

	@Override
	public void onCaptureCompleted(@NonNull CameraCaptureSession session,
								   @NonNull CaptureRequest request,
								   @NonNull TotalCaptureResult result) {
		process(result);
	}

};

由于在点击picture按钮时,在submit request到框架前,将state置为了STATE_WAITING_LOCK,所以这里重点专注STATE_WAITING_LOCK的响应。从流程上看,是要等到af state置为CONTROL_AF_STATE_FOCUSED_LOCKED,也就是已经对焦完成后,触发captureStillPicture()函数,也就是真正的拍照。

4、开始拍照

private void captureStillPicture() {
	try {
		final Activity activity = getActivity();
		if (null == activity || null == mCameraDevice) {
			return;
		}
		// This is the CaptureRequest.Builder that we use to take a picture.
		final CaptureRequest.Builder captureBuilder =
				mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
		captureBuilder.addTarget(mImageReader.getSurface());;

		// Use the same AE and AF modes as the preview.
		captureBuilder.set(CaptureRequest.CONTROL_AF_MODE,
				CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
		setAutoFlash(captureBuilder);

		// Orientation
		int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
		captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, getOrientation(rotation));

		CameraCaptureSession.CaptureCallback CaptureCallback
				= new CameraCaptureSession.CaptureCallback() {

			@Override
			public void onCaptureCompleted(@NonNull CameraCaptureSession session,
										   @NonNull CaptureRequest request,
										   @NonNull TotalCaptureResult result) {
				showToast("Saved: " + mFile);
				Log.d(TAG, mFile.toString());
				unlockFocus();
			}
		};

		mCaptureSession.stopRepeating();
		mCaptureSession.abortCaptures();
		mCaptureSession.capture(captureBuilder.build(), CaptureCallback, null);
	} catch (CameraAccessException e) {
		e.printStackTrace();
	}
}

private void unlockFocus() {
	try {
		// Reset the auto-focus trigger
		mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
				CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
		setAutoFlash(mPreviewRequestBuilder);
		mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback,
				mBackgroundHandler);
		// After this, the camera will go back to the normal state of preview.
		mState = STATE_PREVIEW;
		mCaptureSession.setRepeatingRequest(mPreviewRequest, mCaptureCallback,
				mBackgroundHandler);
	} catch (CameraAccessException e) {
		e.printStackTrace();
	}
}

(1) 创建一个拍照的request
(2) 停预览后通过capture,将拍照的request submit到框架
(3) 返回后弹出一个toast,实际没有保存照片,并调用unlockFocus()函数
(4) 在unlockFocus()函数中恢复预览。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值