Implement 30_FOCUS_API.md: physical autofocus and autoexposure via CameraX API, and disable software blur rendering in Portrait Blur mode

This commit is contained in:
2026-07-06 21:17:42 +07:00
parent cd61e09042
commit 7fdce924b3
2 changed files with 168 additions and 0 deletions
@@ -732,6 +732,21 @@ class MainActivity : AppCompatActivity() {
userSelectedClassFocus = mask[maskY * mW + maskX].toInt()
}
// 1. Gửi lệnh Focus vật lý và đo sáng qua CameraX API (CONTROL_AF_MODE_AUTO, CONTROL_AF_REGIONS, CONTROL_AE_REGIONS)
val cameraCtrl = this@MainActivity.cameraControl
if (cameraCtrl != null) {
try {
val factory = binding.viewFinder.meteringPointFactory
val point = factory.createPoint(event.x, event.y)
val action = androidx.camera.core.FocusMeteringAction.Builder(point, androidx.camera.core.FocusMeteringAction.FLAG_AF or androidx.camera.core.FocusMeteringAction.FLAG_AE)
.setAutoCancelDuration(4, java.util.concurrent.TimeUnit.SECONDS)
.build()
cameraCtrl.startFocusAndMetering(action)
} catch (e: Exception) {
e.printStackTrace()
}
}
// Hiện vòng tròn lấy nét màu cam tại vị trí chạm
val focusRing = binding.viewFocusRing
focusRing.x = event.x - focusRing.width / 2f
@@ -1708,7 +1723,20 @@ class MainActivity : AppCompatActivity() {
return capturedImage
}
// Tắt hoàn toàn thuật toán xử lý mờ/trộn nhân tạo cho Portrait Blur (khi selectedBgAssetPath == null)
// và trả về ảnh thô 100% để sử dụng tiêu cự thấu kính vật lý của camera.
if (selectedBgAssetPath == null && blurIntensity > 0f) {
if (!isStreamMode) {
// Trong chế độ chụp ảnh: Trả về ảnh thô ngay lập tức, không chạy phân đoạn AI
return capturedImage
}
}
if (!isAiSupported) {
// Khi không hỗ trợ AI và chỉ cần Portrait Blur, trả về ảnh thô để dùng thấu kính vật lý
if (selectedBgAssetPath == null && blurIntensity > 0f) {
return capturedImage
}
if (blurIntensity > 0f) {
val opticalIntensity = Math.pow(blurIntensity.toDouble(), 2.5).toFloat()
val radius = (40 * opticalIntensity).toInt().coerceIn(1, 40)
@@ -1745,6 +1773,13 @@ class MainActivity : AppCompatActivity() {
cachedMaskHeight = h
categoryMaskBuffer.rewind()
// Ở chế độ Portrait Blur thấu kính vật lý (selectedBgAssetPath == null),
// sau khi đã lưu cache mask để hỗ trợ xác định đối tượng chạm,
// ta bỏ qua hoàn toàn việc tạo mặt nạ alpha và làm mờ phông nền nhân tạo.
if (selectedBgAssetPath == null) {
return capturedImage
}
// Create and blur alpha mask with Touch-to-Focus class selection
val focusClassId = if (userSelectedClassFocus >= 0) userSelectedClassFocus else -1
val alphaMask = FloatArray(w * h)