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 scale = max(viewWidth / bufferWidth, viewHeight / bufferHeight)
577
- val scaledWidth = bufferWidth * scale
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.setScale(scale, scale)
583
- matrix.postTranslate(dx, dy)
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
- val direct = abs(w / h - targetAspect)
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) {
@@ -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.52.0",
3
+ "version": "7.54.0",
4
4
  "description": "Native-backed document scanner for React Native with customizable overlays.",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",