react-native-rectangle-doc-scanner 10.6.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,37 +96,51 @@ 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...")
108
+ Log.d(TAG, "[CAMERAX] Setting SurfaceProvider for TextureView...")
106
109
 
107
- // Set surface provider with custom executor to see when surface is requested
110
+ // Set custom SurfaceProvider for TextureView
108
111
  previewUseCase.setSurfaceProvider(ContextCompat.getMainExecutor(context)) { request ->
109
- Log.d(TAG, "[CAMERAX] ===== SURFACE REQUESTED =====")
110
- Log.d(TAG, "[CAMERAX] Surface resolution: ${request.resolution}")
111
- Log.d(TAG, "[CAMERAX] Surface camera: ${request.camera}")
112
+ Log.d(TAG, "[CAMERAX] Surface requested - resolution: ${request.resolution}")
112
113
 
113
- // Get the surface from PreviewView and provide it to the request
114
- val surfaceTexture = (previewView.getChildAt(0) as? android.view.TextureView)?.surfaceTexture
114
+ val surfaceTexture = textureView.surfaceTexture
115
115
  if (surfaceTexture != null) {
116
- Log.d(TAG, "[CAMERAX] Got SurfaceTexture from PreviewView")
117
- surfaceTexture.setDefaultBufferSize(request.resolution.width, request.resolution.height)
118
- val surface = android.view.Surface(surfaceTexture)
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)
119
122
  request.provideSurface(surface, ContextCompat.getMainExecutor(context)) { result ->
120
- Log.d(TAG, "[CAMERAX] Surface result: ${result.resultCode}")
123
+ Log.d(TAG, "[CAMERAX] Surface provided - result: ${result.resultCode}")
121
124
  surface.release()
122
125
  }
123
126
  } else {
124
- Log.e(TAG, "[CAMERAX] Failed to get SurfaceTexture - using default provider")
125
- // Fallback to default behavior
126
- previewView.surfaceProvider.onSurfaceRequested(request)
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
+ }
127
144
  }
128
145
  }
129
146
 
@@ -167,7 +184,7 @@ class CameraController(
167
184
 
168
185
  // Add ImageAnalysis after a short delay to avoid timeout
169
186
  if (detectionEnabled) {
170
- previewView.post {
187
+ textureView.post {
171
188
  try {
172
189
  Log.d(TAG, "[CAMERAX] Adding ImageAnalysis...")
173
190
  camera = cameraProvider.bindToLifecycle(
@@ -186,19 +203,6 @@ class CameraController(
186
203
 
187
204
  Log.d(TAG, "[CAMERAX] Camera bound successfully")
188
205
 
189
- // Monitor preview stream state
190
- previewView.previewStreamState.observe(lifecycleOwner) { state ->
191
- Log.d(TAG, "[CAMERAX] PreviewStreamState changed: $state")
192
- when (state) {
193
- androidx.camera.view.PreviewView.StreamState.IDLE ->
194
- Log.w(TAG, "[CAMERAX] Preview stream is IDLE")
195
- androidx.camera.view.PreviewView.StreamState.STREAMING ->
196
- Log.d(TAG, "[CAMERAX] Preview stream is STREAMING ✓")
197
- else ->
198
- Log.d(TAG, "[CAMERAX] Preview stream state: $state")
199
- }
200
- }
201
-
202
206
  } catch (e: Exception) {
203
207
  Log.e(TAG, "[CAMERAX] Use case binding failed", e)
204
208
  }
@@ -373,19 +377,17 @@ class CameraController(
373
377
  }
374
378
 
375
379
  fun refreshTransform() {
376
- // CameraX handles transform automatically via PreviewView
377
- // No manual matrix calculation needed!
378
- 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")
379
382
  }
380
383
 
381
- // Simplified coordinate mapping - PreviewView handles most of the work
384
+ // Simplified coordinate mapping for TextureView
382
385
  fun mapRectangleToView(rectangle: Rectangle?, imageWidth: Int, imageHeight: Int): Rectangle? {
383
386
  if (rectangle == null || imageWidth <= 0 || imageHeight <= 0) return null
384
387
 
385
- // CameraX PreviewView with FILL_CENTER handles scaling and centering
386
- // We just need to scale the coordinates proportionally
387
- val viewWidth = previewView.width.toFloat()
388
- val viewHeight = previewView.height.toFloat()
388
+ // Simple proportional scaling for TextureView
389
+ val viewWidth = textureView.width.toFloat()
390
+ val viewHeight = textureView.height.toFloat()
389
391
 
390
392
  if (viewWidth <= 0 || viewHeight <= 0) return null
391
393
 
@@ -409,9 +411,9 @@ class CameraController(
409
411
  }
410
412
 
411
413
  fun getPreviewViewport(): android.graphics.RectF? {
412
- // With CameraX PreviewView, the viewport is simply the view bounds
413
- val width = previewView.width.toFloat()
414
- 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()
415
417
 
416
418
  if (width <= 0 || height <= 0) return null
417
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.6.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",