react-native-rectangle-doc-scanner 3.246.0 → 3.248.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.
@@ -7,6 +7,7 @@ import android.graphics.Color
7
7
  import android.graphics.Paint
8
8
  import android.graphics.PorterDuff
9
9
  import android.graphics.PorterDuffXfermode
10
+ import org.opencv.core.Point
10
11
  import android.util.Log
11
12
  import android.view.TextureView
12
13
  import android.view.View
@@ -15,6 +16,7 @@ import androidx.lifecycle.Lifecycle
15
16
  import androidx.lifecycle.LifecycleOwner
16
17
  import androidx.lifecycle.LifecycleRegistry
17
18
  import com.facebook.react.bridge.Arguments
19
+ import com.facebook.react.bridge.ReadableMap
18
20
  import com.facebook.react.bridge.WritableMap
19
21
  import com.facebook.react.uimanager.ThemedReactContext
20
22
  import com.facebook.react.uimanager.events.RCTEventEmitter
@@ -53,6 +55,7 @@ class DocumentScannerView(context: ThemedReactContext) : FrameLayout(context), L
53
55
  private var lastDetectedRectangle: Rectangle? = null
54
56
  private var lastDetectedImageWidth = 0
55
57
  private var lastDetectedImageHeight = 0
58
+ private var lastRectangleOnScreen: Rectangle? = null
56
59
 
57
60
  // Coroutine scope for async operations
58
61
  private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
@@ -200,6 +203,7 @@ class DocumentScannerView(context: ThemedReactContext) : FrameLayout(context), L
200
203
  } else {
201
204
  null
202
205
  }
206
+ lastRectangleOnScreen = rectangleOnScreen
203
207
  val quality = when {
204
208
  rectangleOnScreen != null && width > 0 && height > 0 ->
205
209
  DocumentDetector.evaluateRectangleQualityInView(rectangleOnScreen, width, height)
@@ -328,14 +332,26 @@ class DocumentScannerView(context: ThemedReactContext) : FrameLayout(context), L
328
332
  Log.w(TAG, "Rectangle detection failed, using original image", e)
329
333
  null
330
334
  }
331
- if (detectedRectangle == null && lastDetectedRectangle != null && lastDetectedImageWidth > 0 && lastDetectedImageHeight > 0) {
332
- detectedRectangle = scaleRectangleToBitmap(
333
- lastDetectedRectangle!!,
334
- lastDetectedImageWidth,
335
- lastDetectedImageHeight,
336
- bitmap.width,
337
- bitmap.height
338
- )
335
+ if (detectedRectangle == null && lastDetectedImageWidth > 0 && lastDetectedImageHeight > 0) {
336
+ val rectangleFromView = lastRectangleOnScreen?.let {
337
+ viewToImageRectangle(
338
+ it,
339
+ width,
340
+ height,
341
+ lastDetectedImageWidth,
342
+ lastDetectedImageHeight
343
+ )
344
+ }
345
+ val fallbackRect = rectangleFromView ?: lastDetectedRectangle
346
+ if (fallbackRect != null) {
347
+ detectedRectangle = scaleRectangleToBitmap(
348
+ fallbackRect,
349
+ lastDetectedImageWidth,
350
+ lastDetectedImageHeight,
351
+ bitmap.width,
352
+ bitmap.height
353
+ )
354
+ }
339
355
  }
340
356
 
341
357
  // Process image with detected rectangle
@@ -419,14 +435,20 @@ class DocumentScannerView(context: ThemedReactContext) : FrameLayout(context), L
419
435
  imageWidth: Int,
420
436
  imageHeight: Int
421
437
  ) {
438
+ val density = resources.displayMetrics.density.takeIf { it > 0f } ?: 1f
422
439
  val event = Arguments.createMap().apply {
423
440
  putInt("stableCounter", stableCounter)
424
441
  putInt("lastDetectionType", quality.ordinal)
425
442
  putMap("rectangleCoordinates", rectangleCoordinates?.toMap()?.toWritableMap())
426
- putMap("rectangleOnScreen", rectangleOnScreen?.toMap()?.toWritableMap())
443
+ putMap("rectangleOnScreen", rectangleOnScreen?.toMap()?.toWritableMap()?.apply {
444
+ putMap("topLeft", mapPointToDp(getMap("topLeft"), density))
445
+ putMap("topRight", mapPointToDp(getMap("topRight"), density))
446
+ putMap("bottomLeft", mapPointToDp(getMap("bottomLeft"), density))
447
+ putMap("bottomRight", mapPointToDp(getMap("bottomRight"), density))
448
+ })
427
449
  putMap("previewSize", Arguments.createMap().apply {
428
- putInt("width", width)
429
- putInt("height", height)
450
+ putInt("width", (width / density).toInt())
451
+ putInt("height", (height / density).toInt())
430
452
  })
431
453
  putMap("imageSize", Arguments.createMap().apply {
432
454
  putInt("width", imageWidth)
@@ -599,6 +621,52 @@ class DocumentScannerView(context: ThemedReactContext) : FrameLayout(context), L
599
621
  }
600
622
  }
601
623
 
624
+ private fun mapPointToDp(point: ReadableMap?, density: Float): WritableMap? {
625
+ if (point == null) return null
626
+ val map = Arguments.createMap()
627
+ val x = if (point.hasKey("x")) point.getDouble("x") else 0.0
628
+ val y = if (point.hasKey("y")) point.getDouble("y") else 0.0
629
+ map.putDouble("x", x / density)
630
+ map.putDouble("y", y / density)
631
+ return map
632
+ }
633
+
634
+ private fun viewToImageRectangle(
635
+ rectangle: Rectangle,
636
+ viewWidth: Int,
637
+ viewHeight: Int,
638
+ imageWidth: Int,
639
+ imageHeight: Int
640
+ ): Rectangle {
641
+ if (viewWidth == 0 || viewHeight == 0 || imageWidth == 0 || imageHeight == 0) {
642
+ return rectangle
643
+ }
644
+ val scale = max(
645
+ viewWidth.toDouble() / imageWidth.toDouble(),
646
+ viewHeight.toDouble() / imageHeight.toDouble()
647
+ )
648
+ val scaledImageWidth = imageWidth * scale
649
+ val scaledImageHeight = imageHeight * scale
650
+ val offsetX = (scaledImageWidth - viewWidth) / 2.0
651
+ val offsetY = (scaledImageHeight - viewHeight) / 2.0
652
+
653
+ fun mapPoint(point: Point): Point {
654
+ val x = (point.x + offsetX) / scale
655
+ val y = (point.y + offsetY) / scale
656
+ return Point(
657
+ x.coerceIn(0.0, imageWidth.toDouble()),
658
+ y.coerceIn(0.0, imageHeight.toDouble())
659
+ )
660
+ }
661
+
662
+ return Rectangle(
663
+ mapPoint(rectangle.topLeft),
664
+ mapPoint(rectangle.topRight),
665
+ mapPoint(rectangle.bottomLeft),
666
+ mapPoint(rectangle.bottomRight)
667
+ )
668
+ }
669
+
602
670
  private fun scaleRectangleToBitmap(
603
671
  rectangle: Rectangle,
604
672
  srcWidth: Int,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-rectangle-doc-scanner",
3
- "version": "3.246.0",
3
+ "version": "3.248.0",
4
4
  "description": "Native-backed document scanner for React Native with customizable overlays.",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",