Skip to content

Commit 8bea38c

Browse files
ing03201DokySp
authored andcommitted
feat: add internal camera object module [FoKE-Developers#45]
1 parent 59d5f94 commit 8bea38c

File tree

3 files changed

+161
-0
lines changed

3 files changed

+161
-0
lines changed

external/build.gradle.kts

+7
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ dependencies {
2424
// qrcode-kotlin
2525
implementation(libs.qrcode.kotlin)
2626

27+
// camerax
28+
implementation(libs.camerax.core)
29+
implementation(libs.camerax.camera2)
30+
implementation(libs.camerax.lifecycle)
31+
implementation(libs.camerax.view)
32+
implementation(libs.camerax.extensions)
33+
2734
// module dependency
2835
implementation(project(":domain"))
2936

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
package com.foke.together.external.camera.internal
2+
3+
import android.content.Context
4+
import android.graphics.Bitmap
5+
import android.graphics.Matrix
6+
import android.hardware.camera2.CaptureRequest
7+
import android.os.SystemClock
8+
import android.util.Log
9+
import android.util.Range
10+
import android.util.Size
11+
import androidx.annotation.OptIn
12+
import androidx.camera.camera2.Camera2Config
13+
import androidx.camera.camera2.interop.Camera2Interop
14+
import androidx.camera.camera2.interop.ExperimentalCamera2Interop
15+
import androidx.camera.core.AspectRatio
16+
import androidx.camera.core.CameraSelector
17+
import androidx.camera.core.CameraXConfig
18+
import androidx.camera.core.ImageAnalysis
19+
import androidx.camera.lifecycle.ProcessCameraProvider
20+
import dagger.Module
21+
import dagger.Provides
22+
import dagger.hilt.InstallIn
23+
import dagger.hilt.components.SingletonComponent
24+
import kotlinx.coroutines.flow.Flow
25+
import kotlinx.coroutines.flow.flow
26+
import java.util.concurrent.ExecutorService
27+
import java.util.concurrent.Executors
28+
import java.util.concurrent.TimeUnit
29+
import javax.inject.Singleton
30+
31+
@Module
32+
@InstallIn(SingletonComponent::class)
33+
object CameraModule {
34+
private val TAG = CameraModule::class.java.simpleName
35+
private var cameraExecutorService : ExecutorService? = null
36+
37+
38+
// CameraX ImageAnalyzer용 백그라운드 서비스
39+
@Provides
40+
@Singleton
41+
fun clearCameraExecutor(): Boolean{
42+
cameraExecutorService?.shutdown()
43+
cameraExecutorService?.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS)
44+
cameraExecutorService = null
45+
return cameraExecutorService == null
46+
}
47+
48+
@Provides
49+
@Singleton
50+
fun provideCameraSelector(cameraIdx: Int): CameraSelector {
51+
return CameraSelector.Builder()
52+
.requireLensFacing(cameraIdx)
53+
.build()
54+
}
55+
56+
@Provides
57+
@Singleton
58+
fun provideCameraProvider(
59+
context: Context,
60+
): ProcessCameraProvider {
61+
return ProcessCameraProvider.getInstance(context).get()
62+
}
63+
64+
@OptIn(ExperimentalCamera2Interop::class)
65+
@Provides
66+
@Singleton
67+
fun provideImageAnalysis(
68+
rotation: Int
69+
): ImageAnalysis {
70+
val iaBuilder = ImageAnalysis.Builder()
71+
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
72+
.setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888)
73+
.setTargetRotation(rotation)
74+
.setTargetAspectRatio(AspectRatio.RATIO_4_3)
75+
return iaBuilder.build()
76+
}
77+
78+
@Provides
79+
@Singleton
80+
fun provideCameraExecutor(): ExecutorService {
81+
if(cameraExecutorService == null){
82+
cameraExecutorService = Executors.newSingleThreadExecutor()
83+
}
84+
return cameraExecutorService!!
85+
}
86+
87+
fun shutdown(){
88+
if(cameraExecutorService != null) {
89+
cameraExecutorService?.shutdown()
90+
cameraExecutorService?.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS)
91+
cameraExecutorService = null
92+
}
93+
}
94+
95+
@Provides
96+
@Singleton
97+
fun provideCameraXConfig(): CameraXConfig {
98+
return CameraXConfig.Builder
99+
.fromConfig(Camera2Config.defaultConfig())
100+
.setMinimumLoggingLevel(Log.ERROR)
101+
.build()
102+
}
103+
104+
@Provides
105+
@Singleton
106+
fun provideCameraStatus(): Flow<Boolean> = flow {
107+
emit(cameraExecutorService != null)
108+
}
109+
110+
// 미디어 파이프 제공하기 위함
111+
// @Provides
112+
// @Singleton
113+
// fun provideMPImageAnalyzer(
114+
// handLandMarker: HandLandmarker,
115+
// setCameraFrame: (Bitmap) -> Unit,
116+
// cameraCropScale: Float = DEFAULT_CROP_SCALE,
117+
// drawCameraInIndicator: Boolean = false
118+
// ) = ImageAnalysis.Analyzer{ imageProxy ->
119+
// val frameTime = SystemClock.uptimeMillis()
120+
// // Copy out RGB bits from the frame to a bitmap buffer
121+
// val bitmapBuffer =
122+
// Bitmap.createBitmap(
123+
// imageProxy.width,
124+
// imageProxy.height,
125+
// Bitmap.Config.ARGB_8888
126+
// )
127+
// imageProxy.use { bitmapBuffer.copyPixelsFromBuffer(imageProxy.planes[0].buffer) }
128+
// imageProxy.close()
129+
// val newWidth = imageProxy.width / cameraCropScale
130+
// val newHeight = imageProxy.height / cameraCropScale
131+
// val newX = ( imageProxy.width - newWidth ) / 2
132+
// val newY = ( imageProxy.height - newHeight ) / 2
133+
// // if crop scale = 1.0f , not use new bitmap
134+
// var crop = bitmapBuffer
135+
// if ( cameraCropScale > 1.5f ) {
136+
// crop = Bitmap.createBitmap( bitmapBuffer, newX.toInt(), newY.toInt(), newWidth.toInt(), newHeight.toInt() )
137+
// }
138+
//
139+
// // Convert the input Bitmap object to an MPImage object to run inference
140+
// val mpImage = BitmapImageBuilder(crop).build()
141+
// handLandMarker.detectAsync(mpImage, frameTime)
142+
// }
143+
}

gradle/libs.versions.toml

+11
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ ui-graphics-android = "1.7.3"
6464
# qrcode-kotlin --
6565
qrcode-kotlin = "4.1.1"
6666

67+
# camerax --------
68+
camerax = "1.4.1"
69+
6770
# test -----------
6871
junit = "4.13.2"
6972
junit-version = "1.2.1"
@@ -130,6 +133,14 @@ androidx-ui-graphics-android = { group = "androidx.compose.ui", name = "ui-graph
130133
# qrcode-kotlin --
131134
qrcode-kotlin = { group = "io.github.g0dkar", name = "qrcode-kotlin", version.ref = "qrcode-kotlin" }
132135

136+
# camerax --------
137+
camerax-core = { group = "androidx.camera", name = "camera-core", version.ref = "camerax" }
138+
camerax-camera2 = { group = "androidx.camera", name = "camera-camera2", version.ref = "camerax" }
139+
camerax-lifecycle = { group = "androidx.camera", name = "camera-lifecycle", version.ref = "camerax" }
140+
camerax-view = { group = "androidx.camera", name = "camera-view", version.ref = "camerax" }
141+
camerax-extensions = { group = "androidx.camera", name = "camera-extensions", version.ref = "camerax" }
142+
143+
133144
# test -----------
134145
junit = { group = "junit", name = "junit", version.ref = "junit" }
135146
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junit-version" }

0 commit comments

Comments
 (0)