Skip to content

Commit

Permalink
implement tap to focus
Browse files Browse the repository at this point in the history
  • Loading branch information
Kimblebee committed Aug 10, 2023
1 parent ea3ab14 commit fa22c04
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 8 deletions.
3 changes: 3 additions & 0 deletions camera-viewfinder-compose/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ dependencies {
implementation composeBom
androidTestImplementation composeBom

// Compose - Material Design 3
implementation 'androidx.compose.material3:material3'

// Compose - Testing
androidTestImplementation "androidx.compose.ui:ui-test-junit4"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ package com.google.jetpackcamera.viewfinder
import android.graphics.Bitmap
import android.util.Log
import android.view.Surface
import com.google.jetpackcamera.viewfinder.surface.CombinedSurface
import com.google.jetpackcamera.viewfinder.surface.CombinedSurfaceEvent
import com.google.jetpackcamera.viewfinder.surface.SurfaceType
import android.view.View
import androidx.camera.core.Preview.SurfaceProvider
import androidx.camera.core.SurfaceRequest
import androidx.camera.view.PreviewView.ImplementationMode
Expand All @@ -34,6 +32,9 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Modifier
import com.google.jetpackcamera.viewfinder.surface.CombinedSurface
import com.google.jetpackcamera.viewfinder.surface.CombinedSurfaceEvent
import com.google.jetpackcamera.viewfinder.surface.SurfaceType
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.asExecutor
import kotlinx.coroutines.flow.mapNotNull
Expand All @@ -45,7 +46,8 @@ fun CameraPreview(
modifier: Modifier,
implementationMode: ImplementationMode = ImplementationMode.COMPATIBLE,
onSurfaceProviderReady: (SurfaceProvider) -> Unit = {},
onRequestBitmapReady: (() -> Bitmap?) -> Unit
onRequestBitmapReady: (() -> Bitmap?) -> Unit,
setSurfaceView: (View) -> Unit
) {
Log.d(TAG, "CameraPreview")

Expand All @@ -58,6 +60,7 @@ fun CameraPreview(

PreviewSurface(
surfaceRequest = surfaceRequest,
setView = setSurfaceView
)

}
Expand All @@ -68,6 +71,7 @@ fun PreviewSurface(
// onRequestBitmapReady: (() -> Bitmap?) -> Unit,
type: SurfaceType = SurfaceType.TEXTURE_VIEW,
implementationMode: ImplementationMode = ImplementationMode.COMPATIBLE,
setView: (View) -> Unit
) {
Log.d(TAG, "PreviewSurface")

Expand All @@ -89,6 +93,7 @@ fun PreviewSurface(
when (implementationMode) {
ImplementationMode.PERFORMANCE -> TODO()
ImplementationMode.COMPATIBLE -> CombinedSurface(
setView = setView,
onSurfaceEvent = { event ->
surface = when (event) {
is CombinedSurfaceEvent.SurfaceAvailable -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package com.google.jetpackcamera.viewfinder.surface
import android.graphics.Bitmap
import android.util.Log
import android.view.Surface
import android.view.View
import androidx.compose.runtime.Composable
import com.google.jetpackcamera.viewfinder.surface.SurfaceType.*

Expand All @@ -29,6 +30,7 @@ fun CombinedSurface(
onSurfaceEvent: (CombinedSurfaceEvent) -> Unit,
onRequestBitmapReady: (() -> Bitmap?) -> Unit = {},
type: SurfaceType = TEXTURE_VIEW,
setView: (View) -> Unit
) {
Log.d(TAG, "PreviewTexture")

Expand All @@ -46,10 +48,12 @@ fun CombinedSurface(
is SurfaceHolderEvent.SurfaceChanged -> {
// TODO(yasith@)
}

}
}

TEXTURE_VIEW -> Texture(

{
when (it) {
is SurfaceTextureEvent.SurfaceTextureAvailable -> {
Expand All @@ -70,7 +74,8 @@ fun CombinedSurface(
}
true
},
onRequestBitmapReady
onRequestBitmapReady,
setView = setView
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import android.graphics.Bitmap
import android.graphics.SurfaceTexture
import android.util.Log
import android.view.TextureView
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.compose.runtime.Composable
Expand All @@ -34,8 +35,9 @@ private const val TAG = "Texture"
@Composable
fun Texture(
onSurfaceTextureEvent: (SurfaceTextureEvent) -> Boolean = { _ -> true },
onRequestBitmapReady: (() -> Bitmap?) -> Unit
) {
onRequestBitmapReady: (() -> Bitmap?) -> Unit,
setView: (View) -> Unit,
) {
Log.d(TAG, "Texture")

var textureView: TextureView? by remember { mutableStateOf(null) }
Expand Down Expand Up @@ -91,9 +93,11 @@ fun Texture(
}
}, update = {
textureView = it
setView(textureView!!)
onRequestBitmapReady { -> it.bitmap }
}
)

}

sealed interface SurfaceTextureEvent {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.google.jetpackcamera.domain.camera

import android.view.Display
import androidx.camera.core.Preview
import com.google.jetpackcamera.settings.model.CameraAppSettings
import com.google.jetpackcamera.settings.model.FlashModeStatus
Expand Down Expand Up @@ -51,8 +52,11 @@ interface CameraUseCase {
fun setZoomScale(scale: Float): Float

fun setFlashMode(flashModeStatus: FlashModeStatus)

suspend fun flipCamera(isFrontFacing: Boolean)

fun tapToFocus(display: Display, surfaceWidth: Int, surfaceHeight: Int, x:Float, y:Float)

companion object {
const val INVALID_ZOOM_SCALE = -1f
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@ import android.content.ContentValues
import android.provider.MediaStore
import android.util.Log
import android.util.Rational
import android.view.Display
import androidx.camera.core.Camera
import androidx.camera.core.CameraSelector
import androidx.camera.core.CameraSelector.LensFacing
import androidx.camera.core.DisplayOrientedMeteringPointFactory
import androidx.camera.core.FocusMeteringAction
import androidx.camera.core.ImageCapture
import androidx.camera.core.ImageCaptureException
import androidx.camera.core.ImageProxy
Expand Down Expand Up @@ -189,6 +192,29 @@ class CameraXCameraUseCase @Inject constructor(
)
}

override fun tapToFocus(
display: Display,
surfaceWidth: Int,
surfaceHeight: Int,
x: Float,
y: Float
) {
if (camera != null) {
val meteringPoint = DisplayOrientedMeteringPointFactory(
display,
camera!!.cameraInfo,
surfaceWidth.toFloat(),
surfaceHeight.toFloat()
)
.createPoint(x, y);

val action = FocusMeteringAction.Builder(meteringPoint).build()

camera!!.cameraControl.startFocusAndMetering(action)
Log.d(TAG, "Tap to focus on: $meteringPoint")
}
}

override fun setFlashMode(flashModeStatus: FlashModeStatus) {
imageCaptureUseCase.flashMode = when (flashModeStatus) {
FlashModeStatus.OFF -> ImageCapture.FLASH_MODE_OFF // 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.google.jetpackcamera.domain.camera.test

import android.view.Display
import androidx.camera.core.CameraSelector
import androidx.camera.core.Preview
import com.google.jetpackcamera.domain.camera.CameraUseCase
Expand Down Expand Up @@ -89,4 +90,14 @@ class FakeCameraUseCase : CameraUseCase {
override suspend fun flipCamera(isFrontFacing: Boolean) {
isLensFacingFront = isFrontFacing
}

override fun tapToFocus(
display: Display,
surfaceWidth: Int,
surfaceHeight: Int,
x: Float,
y: Float
) {
TODO("Not yet implemented")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package com.google.jetpackcamera.feature.preview
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.view.View
import androidx.camera.core.Preview.SurfaceProvider
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween
Expand Down Expand Up @@ -48,6 +49,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.Color
Expand All @@ -69,6 +71,7 @@ private const val TAG = "PreviewScreen"
/**
* Screen used for the Preview feature.
*/
@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun PreviewScreen(
onNavigateToSettings: () -> Unit,
Expand All @@ -85,6 +88,7 @@ fun PreviewScreen(
Log.d(TAG, "onSurfaceProviderReady")
deferredSurfaceProvider.complete(it)
}
lateinit var viewInfo: View
var zoomScale by remember { mutableStateOf(1f) }
var zoomScaleShow by remember { mutableStateOf(false) }
val zoomHandler = Handler(Looper.getMainLooper())
Expand Down Expand Up @@ -118,16 +122,33 @@ fun PreviewScreen(
onDoubleTap = { offset ->
Log.d(TAG, "onDoubleTap $offset")
viewModel.flipCamera()
},
onTap = { offset ->
try {
viewModel.tapToFocus(
viewInfo.display,
viewInfo.width,
viewInfo.height,
offset.x, offset.y
)
Log.d(TAG, "onTap $offset")
} catch (e: UninitializedPropertyAccessException) {
Log.d(TAG, "onTap $offset")
e.printStackTrace()
}
}
)
}
},
) {
CameraPreview(
modifier = Modifier
.fillMaxSize(),
onSurfaceProviderReady = onSurfaceProviderReady,
onRequestBitmapReady = {
val bitmap = it.invoke()
},
setSurfaceView = { s: View ->
viewInfo = s
}
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.google.jetpackcamera.feature.preview

import android.util.Log
import android.view.Display
import androidx.camera.core.ImageCaptureException
import androidx.camera.core.Preview.SurfaceProvider
import androidx.lifecycle.ViewModel
Expand Down Expand Up @@ -208,4 +209,14 @@ class PreviewViewModel @Inject constructor(
)
}
}

fun tapToFocus(display: Display, surfaceWidth: Int, surfaceHeight: Int, x: Float, y: Float) {
cameraUseCase.tapToFocus(
display = display,
surfaceWidth = surfaceWidth,
surfaceHeight = surfaceHeight,
x = x,
y = y
)
}
}

0 comments on commit fa22c04

Please sign in to comment.