Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,14 @@ class Camera2Source(context: Context): VideoSource() {
return camera.tapToFocus(view, event)
}

fun tapToMeterExposure(view: View, event: MotionEvent): Boolean {
return if (isRunning()) camera.tapToMeterExposure(view, event) else false
}

fun tapToMeterWhiteBalance(view: View, event: MotionEvent): Boolean {
return if (isRunning()) camera.tapToMeterWhiteBalance(view, event) else false
}

@JvmOverloads
fun setZoom(event: MotionEvent, delta: Float = 0.1f) {
if (isRunning()) camera.setZoom(event, delta)
Expand Down Expand Up @@ -234,6 +242,16 @@ class Camera2Source(context: Context): VideoSource() {

fun isExposureLockEnabled() = camera.isExposureLockEnabled

fun enableWhiteBalanceLock(): Boolean {
return if (isRunning()) camera.enableWhiteBalanceLock() else false
}

fun disableWhiteBalanceLock() {
if (isRunning()) camera.disableWhiteBalanceLock()
}

fun isWhiteBalanceLockEnabled() = camera.isWhiteBalanceLockEnabled

@JvmOverloads
fun addImageListener(
format: Int,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ class Camera2ApiManager(context: Context) {
private set
var isAutoWhiteBalanceEnabled: Boolean = true
private set
var isWhiteBalanceLockEnabled: Boolean = false
private set
var isRunning: Boolean = false
private set
private var fps = 30
Expand Down Expand Up @@ -409,6 +411,11 @@ class Camera2ApiManager(context: Context) {
val builderInputSurface = this.builderInputSurface ?: return false
val modes = characteristics.secureGet(CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES) ?: return false
if (!modes.contains(mode)) return false
val maxRegionsAwb = characteristics.secureGet(CameraCharacteristics.CONTROL_MAX_REGIONS_AWB) ?: 0
if (maxRegionsAwb > 0) {
val clearRect = MeteringRectangle(0, 0, 0, 0, MeteringRectangle.METERING_WEIGHT_DONT_CARE)
builderInputSurface.set(CaptureRequest.CONTROL_AWB_REGIONS, arrayOf(clearRect))
}
builderInputSurface.set(CaptureRequest.CONTROL_AWB_MODE, mode)
isAutoWhiteBalanceEnabled = applyRequest(builderInputSurface)
return isAutoWhiteBalanceEnabled
Expand Down Expand Up @@ -453,6 +460,11 @@ class Camera2ApiManager(context: Context) {
val builderInputSurface = this.builderInputSurface ?: return false
val modes = characteristics.secureGet(CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES) ?: return false
if (!modes.contains(CaptureRequest.CONTROL_AE_MODE_ON)) return false
val maxRegionsAe = characteristics.secureGet(CameraCharacteristics.CONTROL_MAX_REGIONS_AE) ?: 0
if (maxRegionsAe > 0) {
val clearRect = MeteringRectangle(0, 0, 0, 0, MeteringRectangle.METERING_WEIGHT_DONT_CARE)
builderInputSurface.set(CaptureRequest.CONTROL_AE_REGIONS, arrayOf(clearRect))
}
builderInputSurface.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON)
isAutoExposureEnabled = applyRequest(builderInputSurface)
return isAutoExposureEnabled
Expand Down Expand Up @@ -492,6 +504,30 @@ class Camera2ApiManager(context: Context) {
isExposureLockEnabled = false
}

/**
* Lock auto white balance to the current value. The camera will stop adjusting white balance
* automatically (useful to avoid color shifts from lighting changes).
* @return true if success, false if fail (not supported or called before start camera)
*/
fun enableWhiteBalanceLock(): Boolean {
val characteristics = cameraCharacteristics ?: return false
val builderInputSurface = this.builderInputSurface ?: return false
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val available = characteristics.secureGet(CameraCharacteristics.CONTROL_AWB_LOCK_AVAILABLE) ?: return false
if (!available) return false
}
builderInputSurface.set(CaptureRequest.CONTROL_AWB_LOCK, true)
isWhiteBalanceLockEnabled = applyRequest(builderInputSurface)
return isWhiteBalanceLockEnabled
}

fun disableWhiteBalanceLock() {
val builderInputSurface = this.builderInputSurface ?: return
builderInputSurface.set(CaptureRequest.CONTROL_AWB_LOCK, false)
applyRequest(builderInputSurface)
isWhiteBalanceLockEnabled = false
}

fun enableVideoStabilization(): Boolean {
val characteristics = cameraCharacteristics ?: return false
val builderInputSurface = this.builderInputSurface ?: return false
Expand Down Expand Up @@ -569,24 +605,30 @@ class Camera2ApiManager(context: Context) {
return supportedExposure
}

fun tapToFocus(view: View, event: MotionEvent): Boolean {
val builderInputSurface = this.builderInputSurface ?: return false
val characteristics = cameraCharacteristics ?: return false
val session = cameraCaptureSession ?: return false
if (characteristics.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AF) == 0) return false
val focusTag = "focus"
val sensorArraySize = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE) ?: return false
private fun getTapRect(view: View, event: MotionEvent): MeteringRectangle? {
val characteristics = cameraCharacteristics ?: return null
val sensorArraySize = characteristics.secureGet(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE) ?: return null

val x = event.x
val y = event.y
val focusX = (x / view.width.toFloat()) * sensorArraySize.width()
val focusY = (y / view.height.toFloat()) * sensorArraySize.height()
val focusRect = MeteringRectangle(
return MeteringRectangle(
(focusX - 100).toInt().coerceIn(0, sensorArraySize.width()),
(focusY - 100).toInt().coerceIn(0, sensorArraySize.height()),
(100 * 2).coerceIn(0, sensorArraySize.width()),
(100 * 2).coerceIn(0, sensorArraySize.height()),
MeteringRectangle.METERING_WEIGHT_MAX
)
}

fun tapToFocus(view: View, event: MotionEvent): Boolean {
val builderInputSurface = this.builderInputSurface ?: return false
val session = cameraCaptureSession ?: return false
val characteristics = cameraCharacteristics ?: return false
if ((characteristics.secureGet(CameraCharacteristics.CONTROL_MAX_REGIONS_AF) ?: 0) == 0) return false
val focusRect = getTapRect(view, event) ?: return false
val focusTag = "focus"

val captureCallbackHandler: CameraCaptureSession.CaptureCallback =
object : CameraCaptureSession.CaptureCallback() {
Expand Down Expand Up @@ -621,6 +663,56 @@ class Camera2ApiManager(context: Context) {
}
}

/**
* Tap to meter exposure at a specific point.
*
* @param view The view where the touch event occurred
* @param event The touch event containing coordinates
* @return true if successful, false otherwise
*/
fun tapToMeterExposure(view: View, event: MotionEvent): Boolean {
if (isExposureLockEnabled) return false
val builderInputSurface = this.builderInputSurface ?: return false
val characteristics = cameraCharacteristics ?: return false
if ((characteristics.secureGet(CameraCharacteristics.CONTROL_MAX_REGIONS_AE) ?: 0) == 0) return false
val aeRect = getTapRect(view, event) ?: return false

return try {
builderInputSurface.set(CaptureRequest.CONTROL_AE_REGIONS, arrayOf(aeRect))
builderInputSurface.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON)
isAutoExposureEnabled = applyRequest(builderInputSurface)
isAutoExposureEnabled
} catch (e: Exception) {
Log.e(TAG, "Error setting AE region", e)
false
}
}

/**
* Tap to meter white balance at a specific point.
*
* @param view The view where the touch event occurred
* @param event The touch event containing coordinates
* @return true if successful, false otherwise
*/
fun tapToMeterWhiteBalance(view: View, event: MotionEvent): Boolean {
if (isWhiteBalanceLockEnabled) return false
val builderInputSurface = this.builderInputSurface ?: return false
val characteristics = cameraCharacteristics ?: return false
if ((characteristics.secureGet(CameraCharacteristics.CONTROL_MAX_REGIONS_AWB) ?: 0) == 0) return false
val awbRect = getTapRect(view, event) ?: return false

return try {
builderInputSurface.set(CaptureRequest.CONTROL_AWB_REGIONS, arrayOf(awbRect))
builderInputSurface.set(CaptureRequest.CONTROL_AWB_MODE, CameraMetadata.CONTROL_AWB_MODE_AUTO)
isAutoWhiteBalanceEnabled = applyRequest(builderInputSurface)
isAutoWhiteBalanceEnabled
} catch (e: Exception) {
Log.e(TAG, "Error setting AWB region", e)
false
}
}

/**
* Select camera facing
*
Expand Down Expand Up @@ -961,6 +1053,8 @@ class Camera2ApiManager(context: Context) {

@JvmOverloads
fun closeCamera(resetSurface: Boolean = true) {
isExposureLockEnabled = false
isWhiteBalanceLockEnabled = false
isLanternEnabled = false
zoomLevel = 1.0f
cameraCaptureSession?.close()
Expand Down
25 changes: 25 additions & 0 deletions library/src/main/java/com/pedro/library/base/Camera2Base.java
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,23 @@ public boolean isExposureLockEnabled() {
return cameraManager.isExposureLockEnabled();
}

/**
* Lock auto white balance to the current value. The camera will stop adjusting white balance
* automatically (useful to avoid color shifts from lighting changes).
* @return true if success, false if fail (not supported or called before start camera)
*/
public boolean enableWhiteBalanceLock() {
return cameraManager.enableWhiteBalanceLock();
}

public void disableWhiteBalanceLock() {
cameraManager.disableWhiteBalanceLock();
}

public boolean isWhiteBalanceLockEnabled() {
return cameraManager.isWhiteBalanceLockEnabled();
}

public void setDynamicFps(boolean enabled) {
cameraManager.setDynamicFps(enabled);
}
Expand Down Expand Up @@ -981,6 +998,14 @@ public boolean tapToFocus(View view, MotionEvent event) {
return cameraManager.tapToFocus(view, event);
}

public boolean tapToMeterExposure(View view, MotionEvent event) {
return cameraManager.tapToMeterExposure(view, event);
}

public boolean tapToMeterWhiteBalance(View view, MotionEvent event) {
return cameraManager.tapToMeterWhiteBalance(view, event);
}

public GlInterface getGlInterface() {
return glInterface;
}
Expand Down
Loading