react-native-rectangle-doc-scanner 7.52.0 → 7.54.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.
|
@@ -67,6 +67,9 @@ class CameraController(
|
|
|
67
67
|
|
|
68
68
|
private val pendingCapture = AtomicReference<PendingCapture?>()
|
|
69
69
|
private val analysisInFlight = AtomicBoolean(false)
|
|
70
|
+
private var latestTransform: Matrix? = null
|
|
71
|
+
private var latestBufferWidth = 0
|
|
72
|
+
private var latestBufferHeight = 0
|
|
70
73
|
private val objectDetector = ObjectDetection.getClient(
|
|
71
74
|
ObjectDetectorOptions.Builder()
|
|
72
75
|
.setDetectorMode(ObjectDetectorOptions.STREAM_MODE)
|
|
@@ -208,6 +211,71 @@ class CameraController(
|
|
|
208
211
|
analysisThread.quitSafely()
|
|
209
212
|
}
|
|
210
213
|
|
|
214
|
+
fun mapRectangleToView(rectangle: Rectangle?, imageWidth: Int, imageHeight: Int): Rectangle? {
|
|
215
|
+
val transform = latestTransform ?: return null
|
|
216
|
+
if (rectangle == null || imageWidth <= 0 || imageHeight <= 0) return null
|
|
217
|
+
if (latestBufferWidth <= 0 || latestBufferHeight <= 0) return null
|
|
218
|
+
|
|
219
|
+
val rotationDegrees = computeRotationDegrees()
|
|
220
|
+
val inverseRotation = (360 - rotationDegrees) % 360
|
|
221
|
+
|
|
222
|
+
fun rotatePoint(point: Point): Point {
|
|
223
|
+
return when (inverseRotation) {
|
|
224
|
+
90 -> Point(imageHeight - point.y, point.x)
|
|
225
|
+
180 -> Point(imageWidth - point.x, imageHeight - point.y)
|
|
226
|
+
270 -> Point(point.y, imageWidth - point.x)
|
|
227
|
+
else -> point
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
val rotated = Rectangle(
|
|
232
|
+
rotatePoint(rectangle.topLeft),
|
|
233
|
+
rotatePoint(rectangle.topRight),
|
|
234
|
+
rotatePoint(rectangle.bottomLeft),
|
|
235
|
+
rotatePoint(rectangle.bottomRight)
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
val bufferWidth = if (inverseRotation == 90 || inverseRotation == 270) {
|
|
239
|
+
imageHeight.toDouble()
|
|
240
|
+
} else {
|
|
241
|
+
imageWidth.toDouble()
|
|
242
|
+
}
|
|
243
|
+
val bufferHeight = if (inverseRotation == 90 || inverseRotation == 270) {
|
|
244
|
+
imageWidth.toDouble()
|
|
245
|
+
} else {
|
|
246
|
+
imageHeight.toDouble()
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
val scaleX = latestBufferWidth.toDouble() / bufferWidth
|
|
250
|
+
val scaleY = latestBufferHeight.toDouble() / bufferHeight
|
|
251
|
+
|
|
252
|
+
fun scalePoint(point: Point): Point {
|
|
253
|
+
return Point(point.x * scaleX, point.y * scaleY)
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
val scaled = Rectangle(
|
|
257
|
+
scalePoint(rotated.topLeft),
|
|
258
|
+
scalePoint(rotated.topRight),
|
|
259
|
+
scalePoint(rotated.bottomLeft),
|
|
260
|
+
scalePoint(rotated.bottomRight)
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
val pts = floatArrayOf(
|
|
264
|
+
scaled.topLeft.x.toFloat(), scaled.topLeft.y.toFloat(),
|
|
265
|
+
scaled.topRight.x.toFloat(), scaled.topRight.y.toFloat(),
|
|
266
|
+
scaled.bottomLeft.x.toFloat(), scaled.bottomLeft.y.toFloat(),
|
|
267
|
+
scaled.bottomRight.x.toFloat(), scaled.bottomRight.y.toFloat()
|
|
268
|
+
)
|
|
269
|
+
transform.mapPoints(pts)
|
|
270
|
+
|
|
271
|
+
return Rectangle(
|
|
272
|
+
Point(pts[0].toDouble(), pts[1].toDouble()),
|
|
273
|
+
Point(pts[2].toDouble(), pts[3].toDouble()),
|
|
274
|
+
Point(pts[4].toDouble(), pts[5].toDouble()),
|
|
275
|
+
Point(pts[6].toDouble(), pts[7].toDouble())
|
|
276
|
+
)
|
|
277
|
+
}
|
|
278
|
+
|
|
211
279
|
private fun openCamera() {
|
|
212
280
|
if (cameraDevice != null) {
|
|
213
281
|
return
|
|
@@ -262,6 +330,13 @@ class CameraController(
|
|
|
262
330
|
captureSize = chooseBestSize(captureSizes, previewAspect, null, preferClosestAspect = true)
|
|
263
331
|
?: captureSizes?.maxByOrNull { it.width * it.height }
|
|
264
332
|
|
|
333
|
+
val previewDiff = previewSize?.let { abs(it.width.toDouble() / it.height.toDouble() - targetPreviewAspect) }
|
|
334
|
+
Log.d(
|
|
335
|
+
TAG,
|
|
336
|
+
"[SIZE_SELECTION] targetAspect=$targetPreviewAspect viewAspect=$viewAspect " +
|
|
337
|
+
"previewAspect=$previewAspect diff=$previewDiff selected=${previewSize?.width}x${previewSize?.height}"
|
|
338
|
+
)
|
|
339
|
+
|
|
265
340
|
setupImageReaders()
|
|
266
341
|
Log.d(
|
|
267
342
|
TAG,
|
|
@@ -361,6 +436,7 @@ class CameraController(
|
|
|
361
436
|
val preview = previewSize ?: return
|
|
362
437
|
|
|
363
438
|
surfaceTexture.setDefaultBufferSize(preview.width, preview.height)
|
|
439
|
+
Log.d(TAG, "[CAMERA2] SurfaceTexture defaultBufferSize=${preview.width}x${preview.height}")
|
|
364
440
|
val previewSurface = Surface(surfaceTexture)
|
|
365
441
|
|
|
366
442
|
val targets = mutableListOf(previewSurface)
|
|
@@ -573,19 +649,34 @@ class CameraController(
|
|
|
573
649
|
val isSwapped = rotationDegrees == 90 || rotationDegrees == 270
|
|
574
650
|
val bufferWidth = if (isSwapped) preview.height.toFloat() else preview.width.toFloat()
|
|
575
651
|
val bufferHeight = if (isSwapped) preview.width.toFloat() else preview.height.toFloat()
|
|
576
|
-
val
|
|
577
|
-
|
|
578
|
-
val scaledHeight = bufferHeight * scale
|
|
579
|
-
val dx = (viewWidth - scaledWidth) / 2f
|
|
580
|
-
val dy = (viewHeight - scaledHeight) / 2f
|
|
652
|
+
val bufferRect = RectF(0f, 0f, bufferWidth, bufferHeight)
|
|
653
|
+
bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY())
|
|
581
654
|
|
|
582
|
-
matrix.
|
|
583
|
-
|
|
655
|
+
matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL)
|
|
656
|
+
val scale = max(viewWidth / bufferWidth, viewHeight / bufferHeight)
|
|
657
|
+
matrix.postScale(scale, scale, centerX, centerY)
|
|
584
658
|
if (rotationDegrees != 0) {
|
|
585
659
|
matrix.postRotate(rotationDegrees.toFloat(), centerX, centerY)
|
|
586
660
|
}
|
|
587
661
|
|
|
588
662
|
previewView.setTransform(matrix)
|
|
663
|
+
latestTransform = Matrix(matrix)
|
|
664
|
+
latestBufferWidth = preview.width
|
|
665
|
+
latestBufferHeight = preview.height
|
|
666
|
+
|
|
667
|
+
val pts = floatArrayOf(
|
|
668
|
+
0f, 0f,
|
|
669
|
+
bufferWidth, 0f,
|
|
670
|
+
0f, bufferHeight,
|
|
671
|
+
bufferWidth, bufferHeight
|
|
672
|
+
)
|
|
673
|
+
matrix.mapPoints(pts)
|
|
674
|
+
Log.d(
|
|
675
|
+
TAG,
|
|
676
|
+
"[TRANSFORM] viewClass=${previewView.javaClass.name} isTextureView=${previewView is TextureView} " +
|
|
677
|
+
"buffer=${bufferWidth}x${bufferHeight} scale=$scale center=${centerX}x${centerY} matrix=$matrix " +
|
|
678
|
+
"pts=[${pts[0]},${pts[1]} ${pts[2]},${pts[3]} ${pts[4]},${pts[5]} ${pts[6]},${pts[7]}]"
|
|
679
|
+
)
|
|
589
680
|
Log.d(TAG, "[TRANSFORM] Matrix applied successfully")
|
|
590
681
|
}
|
|
591
682
|
|
|
@@ -620,9 +711,7 @@ class CameraController(
|
|
|
620
711
|
fun aspectDiff(size: Size): Double {
|
|
621
712
|
val w = size.width.toDouble()
|
|
622
713
|
val h = size.height.toDouble()
|
|
623
|
-
|
|
624
|
-
val inverted = abs(h / w - targetAspect)
|
|
625
|
-
return min(direct, inverted)
|
|
714
|
+
return abs(w / h - targetAspect)
|
|
626
715
|
}
|
|
627
716
|
|
|
628
717
|
if (preferClosestAspect) {
|
package/android/src/camera2/kotlin/com/reactnativerectangledocscanner/DocumentScannerView.kt
CHANGED
|
@@ -210,7 +210,8 @@ class DocumentScannerView(context: ThemedReactContext) : FrameLayout(context), L
|
|
|
210
210
|
}
|
|
211
211
|
|
|
212
212
|
val rectangleOnScreen = if (rectangle != null && width > 0 && height > 0) {
|
|
213
|
-
|
|
213
|
+
cameraController?.mapRectangleToView(rectangle, imageWidth, imageHeight)
|
|
214
|
+
?: DocumentDetector.transformRectangleToViewCoordinates(rectangle, imageWidth, imageHeight, width, height)
|
|
214
215
|
} else {
|
|
215
216
|
null
|
|
216
217
|
}
|