react-native-rectangle-doc-scanner 3.201.0 → 3.203.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.
@@ -44,11 +44,14 @@ class CameraController(
44
44
  private var imageReader: ImageReader? = null
45
45
  private var backgroundThread: HandlerThread? = null
46
46
  private var backgroundHandler: Handler? = null
47
+ private var previewLayoutListener: android.view.View.OnLayoutChangeListener? = null
47
48
 
48
49
  private var cameraId: String? = null
49
50
  private var sensorOrientation: Int = 0
50
51
  private var previewSize: Size? = null
51
52
  private var analysisSize: Size? = null
53
+ private var previewChoices: Array<Size> = emptyArray()
54
+ private var analysisChoices: Array<Size> = emptyArray()
52
55
  private var useFrontCamera = false
53
56
  private var torchEnabled = false
54
57
  private var detectionEnabled = true
@@ -62,8 +65,8 @@ class CameraController(
62
65
 
63
66
  companion object {
64
67
  private const val TAG = "CameraController"
65
- private const val MAX_PREVIEW_WIDTH = 1280
66
- private const val MAX_PREVIEW_HEIGHT = 720
68
+ private const val MAX_PREVIEW_WIDTH = 2560
69
+ private const val MAX_PREVIEW_HEIGHT = 1440
67
70
  }
68
71
 
69
72
  private data class LastFrame(
@@ -121,6 +124,13 @@ class CameraController(
121
124
  startBackgroundThread()
122
125
  chooseCamera()
123
126
 
127
+ if (previewLayoutListener == null) {
128
+ previewLayoutListener = android.view.View.OnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
129
+ updatePreviewTransform()
130
+ }
131
+ previewView.addOnLayoutChangeListener(previewLayoutListener)
132
+ }
133
+
124
134
  if (previewView.isAvailable) {
125
135
  openCamera()
126
136
  } else {
@@ -130,6 +140,10 @@ class CameraController(
130
140
 
131
141
  fun stopCamera() {
132
142
  Log.d(TAG, "[CAMERA2] stopCamera called")
143
+ previewLayoutListener?.let { listener ->
144
+ previewView.removeOnLayoutChangeListener(listener)
145
+ }
146
+ previewLayoutListener = null
133
147
  try {
134
148
  captureSession?.close()
135
149
  captureSession = null
@@ -242,8 +256,8 @@ class CameraController(
242
256
  sensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION) ?: 0
243
257
 
244
258
  val streamConfig = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
245
- val previewChoices = streamConfig?.getOutputSizes(SurfaceTexture::class.java) ?: emptyArray()
246
- val analysisChoices = streamConfig?.getOutputSizes(ImageFormat.YUV_420_888) ?: emptyArray()
259
+ previewChoices = streamConfig?.getOutputSizes(SurfaceTexture::class.java) ?: emptyArray()
260
+ analysisChoices = streamConfig?.getOutputSizes(ImageFormat.YUV_420_888) ?: emptyArray()
247
261
 
248
262
  val viewWidth = if (previewView.width > 0) previewView.width else context.resources.displayMetrics.widthPixels
249
263
  val viewHeight = if (previewView.height > 0) previewView.height else context.resources.displayMetrics.heightPixels
@@ -302,8 +316,9 @@ class CameraController(
302
316
  private fun createPreviewSession() {
303
317
  val device = cameraDevice ?: return
304
318
  val texture = previewView.surfaceTexture ?: return
305
- val previewSize = previewSize ?: return
306
- val analysisSize = analysisSize ?: previewSize
319
+ val sizes = ensurePreviewSizes()
320
+ val previewSize = sizes.first ?: return
321
+ val analysisSize = sizes.second ?: previewSize
307
322
 
308
323
  texture.setDefaultBufferSize(previewSize.width, previewSize.height)
309
324
  val previewSurface = Surface(texture)
@@ -358,6 +373,32 @@ class CameraController(
358
373
  }
359
374
  }
360
375
 
376
+ private fun ensurePreviewSizes(): Pair<Size?, Size?> {
377
+ if (previewChoices.isEmpty()) {
378
+ return Pair(previewSize, analysisSize)
379
+ }
380
+
381
+ val viewWidth = if (previewView.width > 0) previewView.width else context.resources.displayMetrics.widthPixels
382
+ val viewHeight = if (previewView.height > 0) previewView.height else context.resources.displayMetrics.heightPixels
383
+ val targetRatio = if (viewWidth > 0 && viewHeight > 0) {
384
+ viewWidth.toFloat() / viewHeight.toFloat()
385
+ } else {
386
+ null
387
+ }
388
+
389
+ val newPreview = chooseSize(previewChoices, MAX_PREVIEW_WIDTH, MAX_PREVIEW_HEIGHT, targetRatio)
390
+ val newAnalysis = chooseSize(analysisChoices, MAX_PREVIEW_WIDTH, MAX_PREVIEW_HEIGHT, targetRatio)
391
+
392
+ if (newPreview != null && newPreview != previewSize) {
393
+ previewSize = newPreview
394
+ }
395
+ if (newAnalysis != null && newAnalysis != analysisSize) {
396
+ analysisSize = newAnalysis
397
+ }
398
+
399
+ return Pair(previewSize, analysisSize)
400
+ }
401
+
361
402
  private fun updatePreviewTransform() {
362
403
  val previewSize = previewSize ?: return
363
404
  adjustPreviewLayout(previewSize)
@@ -564,21 +605,24 @@ class CameraController(
564
605
  val maxCandidates = choices.filter { it.width <= maxWidth && it.height <= maxHeight }
565
606
  val candidates = if (maxCandidates.isNotEmpty()) maxCandidates else choices.toList()
566
607
 
567
- val ratioFiltered = if (targetRatio != null) {
568
- candidates.filter { size ->
569
- val ratio = if (targetRatio < 1f) {
608
+ if (targetRatio == null) {
609
+ return candidates.sortedBy { it.width * it.height }.last()
610
+ }
611
+
612
+ val normalizedTarget = targetRatio
613
+ val sorted = candidates.sortedWith(
614
+ compareBy<Size> { size ->
615
+ val ratio = if (normalizedTarget < 1f) {
570
616
  size.height.toFloat() / size.width.toFloat()
571
617
  } else {
572
618
  size.width.toFloat() / size.height.toFloat()
573
619
  }
574
- kotlin.math.abs(ratio - targetRatio) <= 0.05f
620
+ kotlin.math.abs(ratio - normalizedTarget)
621
+ }.thenByDescending { size ->
622
+ size.width * size.height
575
623
  }
576
- } else {
577
- emptyList()
578
- }
579
-
580
- val pickFrom = if (ratioFiltered.isNotEmpty()) ratioFiltered else candidates
581
- return pickFrom.sortedBy { it.width * it.height }.last()
624
+ )
625
+ return sorted.first()
582
626
  }
583
627
 
584
628
  private fun startBackgroundThread() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-rectangle-doc-scanner",
3
- "version": "3.201.0",
3
+ "version": "3.203.0",
4
4
  "description": "Native-backed document scanner for React Native with customizable overlays.",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",