react-native-rectangle-doc-scanner 7.13.0 → 7.15.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.
@@ -20,6 +20,7 @@ import android.media.ImageReader
20
20
  import android.os.Handler
21
21
  import android.os.HandlerThread
22
22
  import android.util.Log
23
+ import android.util.SparseIntArray
23
24
  import android.util.Size
24
25
  import android.view.Surface
25
26
  import android.view.TextureView
@@ -35,6 +36,7 @@ import java.io.ByteArrayInputStream
35
36
  import java.util.concurrent.atomic.AtomicReference
36
37
  import java.util.concurrent.atomic.AtomicBoolean
37
38
  import kotlin.math.abs
39
+ import kotlin.math.max
38
40
  import kotlin.math.min
39
41
 
40
42
  class CameraController(
@@ -80,6 +82,12 @@ class CameraController(
80
82
  companion object {
81
83
  private const val TAG = "CameraController"
82
84
  private const val ANALYSIS_ASPECT_TOLERANCE = 0.15
85
+ private val ORIENTATIONS = SparseIntArray().apply {
86
+ append(Surface.ROTATION_0, 90)
87
+ append(Surface.ROTATION_90, 0)
88
+ append(Surface.ROTATION_180, 270)
89
+ append(Surface.ROTATION_270, 180)
90
+ }
83
91
  }
84
92
 
85
93
  private data class PendingCapture(
@@ -484,7 +492,12 @@ class CameraController(
484
492
  val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
485
493
  ?: throw IllegalStateException("Failed to decode JPEG")
486
494
 
487
- val rotation = if (exifRotation != 0) exifRotation else computeRotationDegrees()
495
+ val computedRotation = computeRotationDegrees()
496
+ val rotation = if (exifRotation == 0 || exifRotation != computedRotation) {
497
+ computedRotation
498
+ } else {
499
+ exifRotation
500
+ }
488
501
  val rotated = rotateAndMirror(bitmap, rotation, useFrontCamera)
489
502
  val photoFile = File(pending.outputDirectory, "doc_scan_${System.currentTimeMillis()}.jpg")
490
503
  FileOutputStream(photoFile).use { out ->
@@ -522,13 +535,13 @@ class CameraController(
522
535
  }
523
536
 
524
537
  private fun computeRotationDegrees(): Int {
525
- val displayRotation = displayRotationDegrees()
526
- val rotation = if (useFrontCamera) {
527
- (sensorOrientation + displayRotation) % 360
528
- } else {
529
- (sensorOrientation - displayRotation + 360) % 360
538
+ val displayRotation = previewView.display?.rotation ?: Surface.ROTATION_0
539
+ val deviceRotation = ORIENTATIONS.get(displayRotation, 0)
540
+ var rotation = (sensorOrientation + deviceRotation + 360) % 360
541
+ if (useFrontCamera) {
542
+ rotation = (360 - rotation) % 360
530
543
  }
531
- Log.d(TAG, "[ROTATION] sensor=$sensorOrientation display=$displayRotation front=$useFrontCamera -> rotation=$rotation")
544
+ Log.d(TAG, "[ROTATION] sensor=$sensorOrientation display=${displayRotationDegrees()} front=$useFrontCamera -> rotation=$rotation")
532
545
  return rotation
533
546
  }
534
547
 
@@ -553,28 +566,23 @@ class CameraController(
553
566
  Log.d(TAG, "[TRANSFORM] rotation=$rotationDegrees view=${viewWidth}x${viewHeight} preview=${preview.width}x${preview.height}")
554
567
 
555
568
  val matrix = Matrix()
556
- val centerX = viewWidth / 2f
557
- val centerY = viewHeight / 2f
558
- val isSwapped = rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270
559
- val bufferWidth = if (isSwapped) preview.height.toFloat() else preview.width.toFloat()
560
- val bufferHeight = if (isSwapped) preview.width.toFloat() else preview.height.toFloat()
561
- val scale = maxOf(viewWidth / bufferWidth, viewHeight / bufferHeight)
562
- val scaledWidth = bufferWidth * scale
563
- val scaledHeight = bufferHeight * scale
564
- val dx = (viewWidth - scaledWidth) / 2f
565
- val dy = (viewHeight - scaledHeight) / 2f
566
-
567
- matrix.setScale(scale, scale)
568
- matrix.postTranslate(dx, dy)
569
-
570
- if (rotation != Surface.ROTATION_0) {
571
- val rotateDegrees = when (rotation) {
572
- Surface.ROTATION_90 -> -90f
573
- Surface.ROTATION_180 -> 180f
574
- Surface.ROTATION_270 -> 90f
575
- else -> 0f
576
- }
569
+ val viewRect = RectF(0f, 0f, viewWidth, viewHeight)
570
+ val bufferRect = RectF(0f, 0f, preview.height.toFloat(), preview.width.toFloat())
571
+ val centerX = viewRect.centerX()
572
+ val centerY = viewRect.centerY()
573
+
574
+ if (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) {
575
+ bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY())
576
+ matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL)
577
+ val scale = max(
578
+ viewHeight / preview.height.toFloat(),
579
+ viewWidth / preview.width.toFloat()
580
+ )
581
+ matrix.postScale(scale, scale, centerX, centerY)
582
+ val rotateDegrees = 90f * (rotation - 2)
577
583
  matrix.postRotate(rotateDegrees, centerX, centerY)
584
+ } else if (rotation == Surface.ROTATION_180) {
585
+ matrix.postRotate(180f, centerX, centerY)
578
586
  }
579
587
 
580
588
  previewView.setTransform(matrix)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-rectangle-doc-scanner",
3
- "version": "7.13.0",
3
+ "version": "7.15.0",
4
4
  "description": "Native-backed document scanner for React Native with customizable overlays.",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",