react-native-rectangle-doc-scanner 10.7.0 → 10.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,13 @@
1
1
  package com.reactnativerectangledocscanner
2
2
 
3
3
  import android.content.Context
4
+ import android.graphics.SurfaceTexture
4
5
  import android.util.Log
6
+ import android.util.Size
7
+ import android.view.Surface
8
+ import android.view.TextureView
5
9
  import androidx.camera.core.*
6
10
  import androidx.camera.lifecycle.ProcessCameraProvider
7
- import androidx.camera.view.PreviewView
8
11
  import androidx.core.content.ContextCompat
9
12
  import androidx.lifecycle.LifecycleOwner
10
13
  import com.google.mlkit.vision.common.InputImage
@@ -16,12 +19,12 @@ import java.util.concurrent.Executors
16
19
 
17
20
  /**
18
21
  * CameraX-based camera controller for document scanning
19
- * Handles Preview, ImageAnalysis (ML Kit + OpenCV), and ImageCapture
22
+ * Handles Preview (via TextureView), ImageAnalysis (ML Kit + OpenCV), and ImageCapture
20
23
  */
21
24
  class CameraController(
22
25
  private val context: Context,
23
26
  private val lifecycleOwner: LifecycleOwner,
24
- private val previewView: PreviewView
27
+ private val textureView: TextureView
25
28
  ) {
26
29
  private var camera: Camera? = null
27
30
  private var cameraProvider: ProcessCameraProvider? = null
@@ -93,19 +96,53 @@ class CameraController(
93
96
  CameraSelector.DEFAULT_BACK_CAMERA
94
97
  }
95
98
 
96
- // Preview UseCase
97
- Log.d(TAG, "[CAMERAX] PreviewView size: ${previewView.width}x${previewView.height}")
98
- Log.d(TAG, "[CAMERAX] PreviewView visibility: ${previewView.visibility}")
99
- Log.d(TAG, "[CAMERAX] PreviewView scaleType: ${previewView.scaleType}")
100
- Log.d(TAG, "[CAMERAX] PreviewView implementationMode: ${previewView.implementationMode}")
99
+ // Preview UseCase with TextureView
100
+ Log.d(TAG, "[CAMERAX] TextureView size: ${textureView.width}x${textureView.height}")
101
+ Log.d(TAG, "[CAMERAX] TextureView visibility: ${textureView.visibility}")
102
+ Log.d(TAG, "[CAMERAX] TextureView isAvailable: ${textureView.isAvailable}")
103
+
101
104
  preview = Preview.Builder()
102
105
  .setTargetResolution(android.util.Size(1920, 1080)) // 16:9 resolution
103
106
  .build()
104
107
  .also { previewUseCase ->
105
- Log.d(TAG, "[CAMERAX] Setting SurfaceProvider...")
106
-
107
- // Use PreviewView's default SurfaceProvider
108
- previewUseCase.setSurfaceProvider(ContextCompat.getMainExecutor(context), previewView.surfaceProvider)
108
+ Log.d(TAG, "[CAMERAX] Setting SurfaceProvider for TextureView...")
109
+
110
+ // Set custom SurfaceProvider for TextureView
111
+ previewUseCase.setSurfaceProvider(ContextCompat.getMainExecutor(context)) { request ->
112
+ Log.d(TAG, "[CAMERAX] Surface requested - resolution: ${request.resolution}")
113
+
114
+ val surfaceTexture = textureView.surfaceTexture
115
+ if (surfaceTexture != null) {
116
+ Log.d(TAG, "[CAMERAX] SurfaceTexture available, providing surface")
117
+ surfaceTexture.setDefaultBufferSize(
118
+ request.resolution.width,
119
+ request.resolution.height
120
+ )
121
+ val surface = Surface(surfaceTexture)
122
+ request.provideSurface(surface, ContextCompat.getMainExecutor(context)) { result ->
123
+ Log.d(TAG, "[CAMERAX] Surface provided - result: ${result.resultCode}")
124
+ surface.release()
125
+ }
126
+ } else {
127
+ Log.e(TAG, "[CAMERAX] SurfaceTexture is null! Waiting for TextureView to be ready...")
128
+ // Set listener for when SurfaceTexture becomes available
129
+ textureView.surfaceTextureListener = object : TextureView.SurfaceTextureListener {
130
+ override fun onSurfaceTextureAvailable(st: SurfaceTexture, width: Int, height: Int) {
131
+ Log.d(TAG, "[CAMERAX] SurfaceTexture now available ($width x $height)")
132
+ st.setDefaultBufferSize(request.resolution.width, request.resolution.height)
133
+ val surface = Surface(st)
134
+ request.provideSurface(surface, ContextCompat.getMainExecutor(context)) { result ->
135
+ Log.d(TAG, "[CAMERAX] Surface provided (delayed) - result: ${result.resultCode}")
136
+ surface.release()
137
+ }
138
+ }
139
+
140
+ override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture, width: Int, height: Int) {}
141
+ override fun onSurfaceTextureDestroyed(surface: SurfaceTexture): Boolean = true
142
+ override fun onSurfaceTextureUpdated(surface: SurfaceTexture) {}
143
+ }
144
+ }
145
+ }
109
146
 
110
147
  Log.d(TAG, "[CAMERAX] SurfaceProvider set successfully")
111
148
  }
@@ -147,7 +184,7 @@ class CameraController(
147
184
 
148
185
  // Add ImageAnalysis after a short delay to avoid timeout
149
186
  if (detectionEnabled) {
150
- previewView.post {
187
+ textureView.post {
151
188
  try {
152
189
  Log.d(TAG, "[CAMERAX] Adding ImageAnalysis...")
153
190
  camera = cameraProvider.bindToLifecycle(
@@ -166,19 +203,6 @@ class CameraController(
166
203
 
167
204
  Log.d(TAG, "[CAMERAX] Camera bound successfully")
168
205
 
169
- // Monitor preview stream state
170
- previewView.previewStreamState.observe(lifecycleOwner) { state ->
171
- Log.d(TAG, "[CAMERAX] PreviewStreamState changed: $state")
172
- when (state) {
173
- androidx.camera.view.PreviewView.StreamState.IDLE ->
174
- Log.w(TAG, "[CAMERAX] Preview stream is IDLE")
175
- androidx.camera.view.PreviewView.StreamState.STREAMING ->
176
- Log.d(TAG, "[CAMERAX] Preview stream is STREAMING ✓")
177
- else ->
178
- Log.d(TAG, "[CAMERAX] Preview stream state: $state")
179
- }
180
- }
181
-
182
206
  } catch (e: Exception) {
183
207
  Log.e(TAG, "[CAMERAX] Use case binding failed", e)
184
208
  }
@@ -353,19 +377,17 @@ class CameraController(
353
377
  }
354
378
 
355
379
  fun refreshTransform() {
356
- // CameraX handles transform automatically via PreviewView
357
- // No manual matrix calculation needed!
358
- Log.d(TAG, "[CAMERAX] Transform refresh requested - handled automatically by PreviewView")
380
+ // CameraX with TextureView - no manual transform needed
381
+ Log.d(TAG, "[CAMERAX] Transform refresh requested - handled automatically")
359
382
  }
360
383
 
361
- // Simplified coordinate mapping - PreviewView handles most of the work
384
+ // Simplified coordinate mapping for TextureView
362
385
  fun mapRectangleToView(rectangle: Rectangle?, imageWidth: Int, imageHeight: Int): Rectangle? {
363
386
  if (rectangle == null || imageWidth <= 0 || imageHeight <= 0) return null
364
387
 
365
- // CameraX PreviewView with FILL_CENTER handles scaling and centering
366
- // We just need to scale the coordinates proportionally
367
- val viewWidth = previewView.width.toFloat()
368
- val viewHeight = previewView.height.toFloat()
388
+ // Simple proportional scaling for TextureView
389
+ val viewWidth = textureView.width.toFloat()
390
+ val viewHeight = textureView.height.toFloat()
369
391
 
370
392
  if (viewWidth <= 0 || viewHeight <= 0) return null
371
393
 
@@ -389,9 +411,9 @@ class CameraController(
389
411
  }
390
412
 
391
413
  fun getPreviewViewport(): android.graphics.RectF? {
392
- // With CameraX PreviewView, the viewport is simply the view bounds
393
- val width = previewView.width.toFloat()
394
- val height = previewView.height.toFloat()
414
+ // With TextureView, the viewport is simply the view bounds
415
+ val width = textureView.width.toFloat()
416
+ val height = textureView.height.toFloat()
395
417
 
396
418
  if (width <= 0 || height <= 0) return null
397
419
 
@@ -10,8 +10,8 @@ import android.graphics.PorterDuffXfermode
10
10
  import org.opencv.core.Point
11
11
  import android.util.Log
12
12
  import android.view.View
13
+ import android.view.TextureView
13
14
  import android.widget.FrameLayout
14
- import androidx.camera.view.PreviewView
15
15
  import androidx.lifecycle.Lifecycle
16
16
  import androidx.lifecycle.LifecycleOwner
17
17
  import androidx.lifecycle.LifecycleRegistry
@@ -28,7 +28,7 @@ import kotlin.math.max
28
28
 
29
29
  class DocumentScannerView(context: ThemedReactContext) : FrameLayout(context), LifecycleOwner {
30
30
  private val themedContext = context
31
- private val previewView: PreviewView
31
+ private val previewView: TextureView
32
32
  private val overlayView: OverlayView
33
33
  private val useNativeOverlay = false
34
34
  private var cameraController: CameraController? = null
@@ -81,21 +81,19 @@ class DocumentScannerView(context: ThemedReactContext) : FrameLayout(context), L
81
81
  lifecycleRegistry.currentState = Lifecycle.State.INITIALIZED
82
82
  Log.d(TAG, "[INIT] Lifecycle state: ${lifecycleRegistry.currentState}")
83
83
 
84
- // Create preview view (CameraX PreviewView)
85
- Log.d(TAG, "[INIT] Creating PreviewView...")
86
- previewView = PreviewView(context).apply {
84
+ // Create TextureView for camera preview (CameraX compatible)
85
+ Log.d(TAG, "[INIT] Creating TextureView...")
86
+ previewView = TextureView(context).apply {
87
87
  layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
88
88
  visibility = View.VISIBLE
89
89
  keepScreenOn = true
90
- implementationMode = PreviewView.ImplementationMode.COMPATIBLE // Use TextureView - more compatible with React Native
91
- scaleType = PreviewView.ScaleType.FILL_CENTER // Fill and center the preview
92
90
  }
93
- Log.d(TAG, "[INIT] PreviewView created: $previewView")
94
- Log.d(TAG, "[INIT] PreviewView visibility: ${previewView.visibility}")
91
+ Log.d(TAG, "[INIT] TextureView created: $previewView")
92
+ Log.d(TAG, "[INIT] TextureView visibility: ${previewView.visibility}")
95
93
 
96
- Log.d(TAG, "[INIT] Adding PreviewView to parent...")
94
+ Log.d(TAG, "[INIT] Adding TextureView to parent...")
97
95
  addView(previewView, 0) // Add at index 0 (back)
98
- Log.d(TAG, "[INIT] PreviewView added, childCount: $childCount")
96
+ Log.d(TAG, "[INIT] TextureView added, childCount: $childCount")
99
97
 
100
98
  // Create overlay view for drawing rectangle
101
99
  Log.d(TAG, "[INIT] Creating OverlayView...")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-rectangle-doc-scanner",
3
- "version": "10.7.0",
3
+ "version": "10.8.0",
4
4
  "description": "Native-backed document scanner for React Native with customizable overlays.",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",