如下內(nèi)容方便有Camera2基礎(chǔ)人查看晴埂,如不了解Camera2的人不建議查看澳泵。
拍照流程
先執(zhí)行CaptureRequest.CONTROL_AF_TRIGGER_START鎖定AF授翻,然后根據(jù)回調(diào)不斷判斷AF狀態(tài)刚梭,偽代碼實現(xiàn)如下
Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
if (afState == null) {
//--執(zhí)行拍照`
} else if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState ||
CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) {
//--判斷AE狀態(tài)
}
判斷AF狀態(tài)是lock或者unlock之后還需要在進一步判斷AE狀態(tài)是否收斂重慢,然后在執(zhí)行拍照。AF狀態(tài)lock或unlock后判斷AE狀態(tài)判斷偽代碼如下
if (afState == null) {
`//--執(zhí)行拍照`
} else if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState ||
CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) {
if (aeState == null ||
aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
//--執(zhí)行拍照
} else {
//--AE未收斂师溅,主動執(zhí)行AE_trigger_start
}
}
如果AE未收斂則主動觸發(fā)一次AE操作執(zhí)行CONTROL_AE_PRECAPTURE_TRIGGER_START茅信,然后根據(jù)Capture回調(diào)判斷AE狀態(tài),偽代碼如下:
Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
if (aeState == null ||
aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE ||
aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED) {
//--鎖定AE
}
AE收斂完成墓臭,為了確保場景亮度變化自動觸發(fā)AE蘸鲸,這里需要鎖定AE,偽代碼如下
final CaptureRequest.Builder captureBuilder;
try {
captureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureBuilder.addTarget(mPreviewSurface);
setAutoFlash(captureBuilder);
//--鎖定AE
captureBuilder.set(CaptureRequest.CONTROL_AE_LOCK, Boolean.TRUE);
try {
mCaptureSession.setRepeatingRequest(captureBuilder.build(), mCaptureCallback, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
Log.d("ArMn", "--------STATE_WATTING_LOCK_AE--------Excepture" );
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
//---監(jiān)聽AE LOCK狀態(tài)
if (aeState == null || aeState == CaptureResult.CONTROL_AE_STATE_LOCKED) {
//--------執(zhí)行拍照
}
在AF和AE都滿足拍照條件后起便,執(zhí)行拍照棚贾。如上是拍照中AF和AE狀態(tài)處理流程,也是確保圖片質(zhì)量的關(guān)鍵點榆综。
現(xiàn)在我們討論下如何在每次拍照前觸發(fā)一次閃光燈
在每次拍照前觸發(fā)閃光燈需要遵循多個條件
- 條件一
AE_MODE需要設置成CONTROL_AE_MODE_ON_ALWAYS_FLASH - 條件二
FLASH_MODE需要設置成FLASH_MODE_SINGLE
完整代碼實現(xiàn)如下:
按下拍照按鈕
private void takePicture() {
lockFocus();
}
鎖AF(如果在鎖定AF之前設置了CONTROL_AE_REGIONS,則AF LOCK會觸發(fā)打閃)
private void lockFocus() {
try {
// This is how to tell the camera to lock focus.
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
CaptureRequest.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();
}
}
判斷AF狀態(tài)
case STATE_WAITING_LOCK: {
Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
Log.d("ArMn", "--------- STATE_WAITING_LOCK-------afState: " + afState);
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;
Log.d("ArMn", "--------captureStillPicture--------");
captureStillPicture();
} else {
Log.d("ArMn", "--------runPrecaptureSequence--------");
runPrecaptureSequence();
}
}
break;
}
執(zhí)行AE打閃(如果AF沒有觸發(fā)打閃铸史,則此處會觸發(fā)打閃)
private void runPrecaptureSequence() {
try {
final CaptureRequest.Builder captureBuilder =
mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)
captureBuilder.addTarget(mImageReader.getSurface());
setAutoFlash(captureBuilder);
captureBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
// This is how to tell the camera to trigger.
// Tell #mCaptureCallback to wait for the precapture sequence to be set.
mState = STATE_WAITING_PRECAPTURE;
mCaptureSession.capture(captureBuilder.build(), mCaptureCallback,
mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
判斷AE打閃狀態(tài)
case STATE_WAITING_PRECAPTURE: {
// CONTROL_AE_STATE can be null on some devices
Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
Log.d("ArMn", "--------STATE_WAITING_PRECAPTURE--------aeState: " + aeState);
if (aeState == null ||
aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE ||
aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED) {
mState = STATE_WATTING_LOCK_AE;
}
break;
鎖定AE狀態(tài)
private void lockAe() {
mState = STATE_WAITING_NON_PRECAPTURE;
final CaptureRequest.Builder captureBuilder;
try {
captureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureBuilder.addTarget(mPreviewSurface);
setAutoFlash(captureBuilder);
captureBuilder.set(CaptureRequest.CONTROL_AE_LOCK, Boolean.TRUE);
try {
mCaptureSession.setRepeatingRequest(captureBuilder.build(), mCaptureCallback, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
Log.d("ArMn", "--------STATE_WATTING_LOCK_AE--------Excepture" );
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
判斷AE鎖定狀態(tài)
case STATE_WAITING_NON_PRECAPTURE: {
// CONTROL_AE_STATE can be null on some devices
Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
Log.d("ArMn", "--------captureStillPicture-- STATE_WAITING_NON_PRECAPTURE ------state: " + aeState);
if (aeState == null || aeState == CaptureResult.CONTROL_AE_STATE_LOCKED) {
mState = STATE_PICTURE_TAKEN;
captureStillPicture();
}
break;
}
執(zhí)行拍照
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);
mCaptureSession.capture(captureBuilder.build(), CaptureCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
注意: 不要在鎖定AE的時候下發(fā)CONTROL_AE_PRECAPTURE_TRIGGER鼻疮,不然會導致閃光燈常亮。 建議每觸發(fā)一次capture都重新創(chuàng)建一次CapureRequest對象琳轿。 如果在觸發(fā)CONTROL_AE_PRECAPTURE_TRIGGER成功之后不鎖定AE判沟,閃光燈會很快關(guān)閉。如果執(zhí)行了鎖定AE會在AE狀態(tài)lock后關(guān)閉
Flash常用的如下設置(摘抄高通Camera源碼)
private void applyFlash(CaptureRequest.Builder request, String value) {
switch (value) {
case "on":
if (mLongshotActive) {
request.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
request.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
} else {
request.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH);
request.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_SINGLE);
}
break;
case "auto":
if (mLongshotActive) {
// When long shot is active, turn off the flash in auto mode
request.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
request.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
} else {
request.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
request.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_SINGLE);
}
break;
case "off":
request.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
request.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
break;
}
}