react-native-rectangle-doc-scanner 7.51.0 → 7.53.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
@@ -559,14 +627,7 @@ class CameraController(
559
627
  val preview = previewSize ?: return
560
628
  if (viewWidth == 0f || viewHeight == 0f) return
561
629
 
562
- val rotation = previewView.display?.rotation ?: Surface.ROTATION_0
563
- val rotationDegrees = when (rotation) {
564
- Surface.ROTATION_0 -> 0
565
- Surface.ROTATION_90 -> 90
566
- Surface.ROTATION_180 -> 180
567
- Surface.ROTATION_270 -> 270
568
- else -> 0
569
- }
630
+ val rotationDegrees = computeRotationDegrees()
570
631
  Log.d(
571
632
  TAG,
572
633
  "[TRANSFORM] rotation=$rotationDegrees view=${viewWidth}x${viewHeight} preview=${preview.width}x${preview.height}"
@@ -577,31 +638,30 @@ class CameraController(
577
638
  val centerX = viewRect.centerX()
578
639
  val centerY = viewRect.centerY()
579
640
 
580
- val isSwapped = rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270
581
- if (isSwapped) {
582
- val bufferRect = RectF(0f, 0f, preview.height.toFloat(), preview.width.toFloat())
583
- bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY())
584
- matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL)
585
- val scale = max(
586
- viewHeight / preview.height.toFloat(),
587
- viewWidth / preview.width.toFloat()
588
- )
589
- matrix.postScale(scale, scale, centerX, centerY)
590
- matrix.postRotate(90f * (rotation - 2), centerX, centerY)
591
- } else {
592
- val bufferRect = RectF(0f, 0f, preview.width.toFloat(), preview.height.toFloat())
593
- matrix.setRectToRect(bufferRect, viewRect, Matrix.ScaleToFit.CENTER)
594
- val scale = max(
595
- viewWidth / preview.width.toFloat(),
596
- viewHeight / preview.height.toFloat()
597
- )
598
- matrix.postScale(scale, scale, centerX, centerY)
599
- if (rotation == Surface.ROTATION_180) {
600
- matrix.postRotate(180f, centerX, centerY)
601
- }
641
+ val bufferWidth = preview.width.toFloat()
642
+ val bufferHeight = preview.height.toFloat()
643
+ val bufferRect = RectF(0f, 0f, bufferWidth, bufferHeight)
644
+ val rotatedRect = RectF(bufferRect)
645
+
646
+ if (rotationDegrees != 0) {
647
+ matrix.postRotate(rotationDegrees.toFloat(), bufferRect.centerX(), bufferRect.centerY())
648
+ matrix.mapRect(rotatedRect, bufferRect)
602
649
  }
603
650
 
651
+ val scale = max(viewWidth / rotatedRect.width(), viewHeight / rotatedRect.height())
652
+ matrix.postScale(scale, scale, rotatedRect.centerX(), rotatedRect.centerY())
653
+ matrix.postTranslate(centerX - rotatedRect.centerX(), centerY - rotatedRect.centerY())
654
+
604
655
  previewView.setTransform(matrix)
656
+ latestTransform = Matrix(matrix)
657
+ latestBufferWidth = preview.width
658
+ latestBufferHeight = preview.height
659
+ Log.d(
660
+ TAG,
661
+ "[TRANSFORM] viewClass=${previewView.javaClass.name} isTextureView=${previewView is TextureView} " +
662
+ "buffer=${preview.width}x${preview.height} rotated=${rotatedRect.width()}x${rotatedRect.height()} " +
663
+ "scale=$scale center=${centerX}x${centerY} matrix=$matrix"
664
+ )
605
665
  Log.d(TAG, "[TRANSFORM] Matrix applied successfully")
606
666
  }
607
667
 
@@ -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
- DocumentDetector.transformRectangleToViewCoordinates(rectangle, imageWidth, imageHeight, width, height)
213
+ cameraController?.mapRectangleToView(rectangle, imageWidth, imageHeight)
214
+ ?: DocumentDetector.transformRectangleToViewCoordinates(rectangle, imageWidth, imageHeight, width, height)
214
215
  } else {
215
216
  null
216
217
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-rectangle-doc-scanner",
3
- "version": "7.51.0",
3
+ "version": "7.53.0",
4
4
  "description": "Native-backed document scanner for React Native with customizable overlays.",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",