react-native-rectangle-doc-scanner 7.62.0 → 7.63.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.
@@ -355,11 +355,13 @@ class CameraController(
355
355
  captureSize = chooseBestSize(captureSizes, previewAspect, null, preferClosestAspect = true)
356
356
  ?: captureSizes?.maxByOrNull { it.width * it.height }
357
357
 
358
- val previewDiff = previewSize?.let { abs(it.width.toDouble() / it.height.toDouble() - targetPreviewAspect) }
358
+ val viewAspectNormalized = max(viewAspect, 1.0 / viewAspect)
359
+ val previewAspectNormalized = max(previewAspect, 1.0 / previewAspect)
360
+ val previewDiff = abs(previewAspectNormalized - viewAspectNormalized)
359
361
  Log.d(
360
362
  TAG,
361
- "[SIZE_SELECTION] targetAspect=$targetPreviewAspect viewAspect=$viewAspect " +
362
- "previewAspect=$previewAspect diff=$previewDiff selected=${previewSize?.width}x${previewSize?.height}"
363
+ "[SIZE_SELECTION] targetAspect=$viewAspectNormalized viewAspect=$viewAspectNormalized " +
364
+ "previewAspect=$previewAspectNormalized diff=$previewDiff selected=${previewSize?.width}x${previewSize?.height}"
363
365
  )
364
366
 
365
367
  setupImageReaders()
@@ -662,47 +664,79 @@ class CameraController(
662
664
 
663
665
  val rotationDegrees = computeRotationDegrees()
664
666
  val displayRotation = displayRotationDegrees()
665
- Log.d(
666
- TAG,
667
- "[TRANSFORM] rotations sensor=$sensorOrientation display=$displayRotation computed=$rotationDegrees view=${viewWidth}x${viewHeight} preview=${preview.width}x${preview.height}"
668
- )
669
667
 
670
- val matrix = Matrix()
671
668
  val viewRect = RectF(0f, 0f, viewWidth, viewHeight)
672
669
  val centerX = viewRect.centerX()
673
670
  val centerY = viewRect.centerY()
674
671
 
675
- val isSwapped = rotationDegrees == 90 || rotationDegrees == 270
676
- val bufferWidth = if (isSwapped) preview.height.toFloat() else preview.width.toFloat()
677
- val bufferHeight = if (isSwapped) preview.width.toFloat() else preview.height.toFloat()
678
- val bufferRect = RectF(0f, 0f, bufferWidth, bufferHeight)
679
- bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY())
672
+ fun buildTransform(appliedRotation: Int): Pair<Matrix, FloatArray> {
673
+ val candidate = Matrix()
674
+ val swap = appliedRotation == 90 || appliedRotation == 270
675
+ val bufferWidth = if (swap) preview.height.toFloat() else preview.width.toFloat()
676
+ val bufferHeight = if (swap) preview.width.toFloat() else preview.height.toFloat()
677
+ val bufferRect = RectF(0f, 0f, bufferWidth, bufferHeight)
678
+ bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY())
679
+
680
+ candidate.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL)
681
+ val scale = max(viewWidth / bufferRect.width(), viewHeight / bufferRect.height())
682
+ candidate.postScale(scale, scale, centerX, centerY)
683
+ if (appliedRotation != 0) {
684
+ candidate.postRotate(appliedRotation.toFloat(), centerX, centerY)
685
+ }
680
686
 
681
- matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL)
682
- val scale = max(viewWidth / bufferRect.width(), viewHeight / bufferRect.height())
683
- matrix.postScale(scale, scale, centerX, centerY)
684
- if (rotationDegrees != 0) {
685
- matrix.postRotate(rotationDegrees.toFloat(), centerX, centerY)
687
+ val pts = floatArrayOf(
688
+ 0f, 0f,
689
+ bufferWidth, 0f,
690
+ 0f, bufferHeight,
691
+ bufferWidth, bufferHeight
692
+ )
693
+ candidate.mapPoints(pts)
694
+ return Pair(candidate, pts)
686
695
  }
687
696
 
688
- previewView.setTransform(matrix)
689
- latestTransform = Matrix(matrix)
697
+ fun scoreCoverage(pts: FloatArray): Float {
698
+ val minX = min(min(pts[0], pts[2]), min(pts[4], pts[6]))
699
+ val maxX = max(max(pts[0], pts[2]), max(pts[4], pts[6]))
700
+ val minY = min(min(pts[1], pts[3]), min(pts[5], pts[7]))
701
+ val maxY = max(max(pts[1], pts[3]), max(pts[5], pts[7]))
702
+
703
+ val left = max(viewRect.left, minX)
704
+ val top = max(viewRect.top, minY)
705
+ val right = min(viewRect.right, maxX)
706
+ val bottom = min(viewRect.bottom, maxY)
707
+ val intersection = if (right > left && bottom > top) (right - left) * (bottom - top) else 0f
708
+ val viewArea = viewRect.width() * viewRect.height()
709
+ return if (viewArea > 0f) intersection / viewArea else 0f
710
+ }
711
+
712
+ val positive = rotationDegrees
713
+ val negative = if (rotationDegrees == 0) 0 else (360 - rotationDegrees) % 360
714
+ val (matrixPos, ptsPos) = buildTransform(positive)
715
+ val (matrixNeg, ptsNeg) = buildTransform(negative)
716
+ val scorePos = scoreCoverage(ptsPos)
717
+ val scoreNeg = scoreCoverage(ptsNeg)
718
+
719
+ val appliedRotation = if (scoreNeg > scorePos) negative else positive
720
+ val appliedMatrix = if (appliedRotation == positive) matrixPos else matrixNeg
721
+ val appliedPts = if (appliedRotation == positive) ptsPos else ptsNeg
722
+
723
+ Log.d(
724
+ TAG,
725
+ "[TRANSFORM] rotations sensor=$sensorOrientation display=$displayRotation computed=$rotationDegrees applied=$appliedRotation " +
726
+ "view=${viewWidth}x${viewHeight} preview=${preview.width}x${preview.height}"
727
+ )
728
+
729
+ previewView.setTransform(appliedMatrix)
730
+ latestTransform = Matrix(appliedMatrix)
690
731
  latestBufferWidth = preview.width
691
732
  latestBufferHeight = preview.height
692
- latestTransformRotation = rotationDegrees
733
+ latestTransformRotation = appliedRotation
693
734
 
694
- val pts = floatArrayOf(
695
- 0f, 0f,
696
- bufferWidth, 0f,
697
- 0f, bufferHeight,
698
- bufferWidth, bufferHeight
699
- )
700
- matrix.mapPoints(pts)
701
735
  Log.d(
702
736
  TAG,
703
- "[TRANSFORM] viewClass=${previewView.javaClass.name} isTextureView=${previewView is TextureView} " +
704
- "buffer=${bufferWidth}x${bufferHeight} scale=$scale center=${centerX}x${centerY} matrix=$matrix " +
705
- "pts=[${pts[0]},${pts[1]} ${pts[2]},${pts[3]} ${pts[4]},${pts[5]} ${pts[6]},${pts[7]}]"
737
+ "[TRANSFORM] appliedRotation=$appliedRotation scores pos=$scorePos neg=$scoreNeg viewClass=${previewView.javaClass.name} " +
738
+ "isTextureView=${previewView is TextureView} matrix=$appliedMatrix " +
739
+ "pts=[${appliedPts[0]},${appliedPts[1]} ${appliedPts[2]},${appliedPts[3]} ${appliedPts[4]},${appliedPts[5]} ${appliedPts[6]},${appliedPts[7]}]"
706
740
  )
707
741
  val recomputed = computeRotationDegrees()
708
742
  if (rotationDegrees != recomputed) {
@@ -742,7 +776,9 @@ class CameraController(
742
776
  fun aspectDiff(size: Size): Double {
743
777
  val w = size.width.toDouble()
744
778
  val h = size.height.toDouble()
745
- return abs(w / h - targetAspect)
779
+ val aspect = max(w, h) / min(w, h)
780
+ val target = max(targetAspect, 1.0 / targetAspect)
781
+ return abs(aspect - target)
746
782
  }
747
783
 
748
784
  if (preferClosestAspect) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-rectangle-doc-scanner",
3
- "version": "7.62.0",
3
+ "version": "7.63.0",
4
4
  "description": "Native-backed document scanner for React Native with customizable overlays.",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",