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 &&
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
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