react-native-rectangle-doc-scanner 10.22.0 → 10.23.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,7 +355,22 @@ class CameraController(
355
355
  mlBox: android.graphics.Rect?
356
356
  ): Rectangle? {
357
357
  return try {
358
- DocumentDetector.detectRectangleInYUV(nv21, width, height, rotation)
358
+ if (mlBox != null) {
359
+ val frameWidth = if (rotation == 90 || rotation == 270) height else width
360
+ val frameHeight = if (rotation == 90 || rotation == 270) width else height
361
+ val padX = (mlBox.width() * 0.15f).toInt().coerceAtLeast(24)
362
+ val padY = (mlBox.height() * 0.15f).toInt().coerceAtLeast(24)
363
+ val roi = android.graphics.Rect(
364
+ (mlBox.left - padX).coerceAtLeast(0),
365
+ (mlBox.top - padY).coerceAtLeast(0),
366
+ (mlBox.right + padX).coerceAtMost(frameWidth),
367
+ (mlBox.bottom + padY).coerceAtMost(frameHeight)
368
+ )
369
+ DocumentDetector.detectRectangleInYUVWithRoi(nv21, width, height, rotation, roi)
370
+ ?: DocumentDetector.detectRectangleInYUV(nv21, width, height, rotation)
371
+ } else {
372
+ DocumentDetector.detectRectangleInYUV(nv21, width, height, rotation)
373
+ }
359
374
  } catch (e: Exception) {
360
375
  Log.w(TAG, "[CAMERAX] OpenCV detection failed", e)
361
376
  null
@@ -421,20 +436,24 @@ class CameraController(
421
436
  fun mapRectangleToView(rectangle: Rectangle?, imageWidth: Int, imageHeight: Int): Rectangle? {
422
437
  if (rectangle == null || imageWidth <= 0 || imageHeight <= 0) return null
423
438
 
424
- // Simple proportional scaling for TextureView
439
+ // Fit-center scaling to avoid zoom/crop and keep mapping aligned with preview.
425
440
  val viewWidth = textureView.width.toFloat()
426
441
  val viewHeight = textureView.height.toFloat()
427
442
 
428
443
  if (viewWidth <= 0 || viewHeight <= 0) return null
429
444
 
430
- // Simple proportional scaling
431
445
  val scaleX = viewWidth / imageWidth.toFloat()
432
446
  val scaleY = viewHeight / imageHeight.toFloat()
447
+ val scale = scaleX.coerceAtMost(scaleY)
448
+ val scaledWidth = imageWidth * scale
449
+ val scaledHeight = imageHeight * scale
450
+ val offsetX = (viewWidth - scaledWidth) / 2f
451
+ val offsetY = (viewHeight - scaledHeight) / 2f
433
452
 
434
453
  fun scalePoint(point: org.opencv.core.Point): org.opencv.core.Point {
435
454
  return org.opencv.core.Point(
436
- point.x * scaleX,
437
- point.y * scaleY
455
+ point.x * scale + offsetX,
456
+ point.y * scale + offsetY
438
457
  )
439
458
  }
440
459
 
@@ -509,10 +528,10 @@ class CameraController(
509
528
  bufferHeight
510
529
  }
511
530
 
512
- // Scale to fill the view while maintaining aspect ratio
531
+ // Scale to fit within the view while maintaining aspect ratio (no zoom/crop)
513
532
  val scaleX = viewWidth.toFloat() / rotatedBufferWidth.toFloat()
514
533
  val scaleY = viewHeight.toFloat() / rotatedBufferHeight.toFloat()
515
- val scale = scaleX.coerceAtLeast(scaleY) // Use max to fill
534
+ val scale = scaleX.coerceAtMost(scaleY) // Use min to fit
516
535
 
517
536
  Log.d(TAG, "[TRANSFORM] Rotated buffer: ${rotatedBufferWidth}x${rotatedBufferHeight}, ScaleX: $scaleX, ScaleY: $scaleY, Using: $scale")
518
537
 
@@ -684,18 +684,18 @@ class DocumentScannerView(context: ThemedReactContext) : FrameLayout(context), L
684
684
  if (viewWidth == 0 || viewHeight == 0 || imageWidth == 0 || imageHeight == 0) {
685
685
  return rectangle
686
686
  }
687
- val scale = max(
687
+ val scale = min(
688
688
  viewWidth.toDouble() / imageWidth.toDouble(),
689
689
  viewHeight.toDouble() / imageHeight.toDouble()
690
690
  )
691
691
  val scaledImageWidth = imageWidth.toDouble() * scale
692
692
  val scaledImageHeight = imageHeight.toDouble() * scale
693
- val offsetX = (scaledImageWidth - viewWidth) / 2.0
694
- val offsetY = (scaledImageHeight - viewHeight) / 2.0
693
+ val offsetX = (viewWidth - scaledImageWidth) / 2.0
694
+ val offsetY = (viewHeight - scaledImageHeight) / 2.0
695
695
 
696
696
  fun mapPoint(point: Point): Point {
697
- val x = (point.x + offsetX) / scale
698
- val y = (point.y + offsetY) / scale
697
+ val x = (point.x - offsetX) / scale
698
+ val y = (point.y - offsetY) / scale
699
699
  return Point(
700
700
  x.coerceIn(0.0, imageWidth.toDouble()),
701
701
  y.coerceIn(0.0, imageHeight.toDouble())
@@ -421,19 +421,19 @@ class DocumentDetector {
421
421
  return rectangle
422
422
  }
423
423
 
424
- val scale = max(
424
+ val scale = min(
425
425
  viewWidth.toDouble() / imageWidth.toDouble(),
426
426
  viewHeight.toDouble() / imageHeight.toDouble()
427
427
  )
428
428
 
429
429
  val scaledImageWidth = imageWidth * scale
430
430
  val scaledImageHeight = imageHeight * scale
431
- val offsetX = (scaledImageWidth - viewWidth) / 2.0
432
- val offsetY = (scaledImageHeight - viewHeight) / 2.0
431
+ val offsetX = (viewWidth - scaledImageWidth) / 2.0
432
+ val offsetY = (viewHeight - scaledImageHeight) / 2.0
433
433
 
434
434
  fun mapPoint(point: Point): Point {
435
- val x = (point.x * scale) - offsetX
436
- val y = (point.y * scale) - offsetY
435
+ val x = (point.x * scale) + offsetX
436
+ val y = (point.y * scale) + offsetY
437
437
  return Point(
438
438
  x.coerceIn(0.0, viewWidth.toDouble()),
439
439
  y.coerceIn(0.0, viewHeight.toDouble())
@@ -121,14 +121,24 @@ const mirrorRectangleHorizontally = (rectangle, imageWidth) => ({
121
121
  const mapRectangleToView = (rectangle, imageWidth, imageHeight, viewWidth, viewHeight, density) => {
122
122
  const viewWidthPx = viewWidth * density;
123
123
  const viewHeightPx = viewHeight * density;
124
- const scale = Math.max(viewWidthPx / imageWidth, viewHeightPx / imageHeight);
124
+ const scale = react_native_1.Platform.OS === 'ios'
125
+ ? Math.max(viewWidthPx / imageWidth, viewHeightPx / imageHeight)
126
+ : Math.min(viewWidthPx / imageWidth, viewHeightPx / imageHeight);
125
127
  const scaledImageWidth = imageWidth * scale;
126
128
  const scaledImageHeight = imageHeight * scale;
127
- const offsetX = (scaledImageWidth - viewWidthPx) / 2;
128
- const offsetY = (scaledImageHeight - viewHeightPx) / 2;
129
+ const offsetX = react_native_1.Platform.OS === 'ios'
130
+ ? (scaledImageWidth - viewWidthPx) / 2
131
+ : (viewWidthPx - scaledImageWidth) / 2;
132
+ const offsetY = react_native_1.Platform.OS === 'ios'
133
+ ? (scaledImageHeight - viewHeightPx) / 2
134
+ : (viewHeightPx - scaledImageHeight) / 2;
129
135
  const mapPoint = (point) => ({
130
- x: (point.x * scale - offsetX) / density,
131
- y: (point.y * scale - offsetY) / density,
136
+ x: react_native_1.Platform.OS === 'ios'
137
+ ? (point.x * scale - offsetX) / density
138
+ : (point.x * scale + offsetX) / density,
139
+ y: react_native_1.Platform.OS === 'ios'
140
+ ? (point.y * scale - offsetY) / density
141
+ : (point.y * scale + offsetY) / density,
132
142
  });
133
143
  return {
134
144
  topLeft: mapPoint(rectangle.topLeft),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-rectangle-doc-scanner",
3
- "version": "10.22.0",
3
+ "version": "10.23.0",
4
4
  "description": "Native-backed document scanner for React Native with customizable overlays.",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -188,15 +188,30 @@ const mapRectangleToView = (
188
188
  ): Rectangle => {
189
189
  const viewWidthPx = viewWidth * density;
190
190
  const viewHeightPx = viewHeight * density;
191
- const scale = Math.max(viewWidthPx / imageWidth, viewHeightPx / imageHeight);
191
+ const scale =
192
+ Platform.OS === 'ios'
193
+ ? Math.max(viewWidthPx / imageWidth, viewHeightPx / imageHeight)
194
+ : Math.min(viewWidthPx / imageWidth, viewHeightPx / imageHeight);
192
195
  const scaledImageWidth = imageWidth * scale;
193
196
  const scaledImageHeight = imageHeight * scale;
194
- const offsetX = (scaledImageWidth - viewWidthPx) / 2;
195
- const offsetY = (scaledImageHeight - viewHeightPx) / 2;
197
+ const offsetX =
198
+ Platform.OS === 'ios'
199
+ ? (scaledImageWidth - viewWidthPx) / 2
200
+ : (viewWidthPx - scaledImageWidth) / 2;
201
+ const offsetY =
202
+ Platform.OS === 'ios'
203
+ ? (scaledImageHeight - viewHeightPx) / 2
204
+ : (viewHeightPx - scaledImageHeight) / 2;
196
205
 
197
206
  const mapPoint = (point: Point): Point => ({
198
- x: (point.x * scale - offsetX) / density,
199
- y: (point.y * scale - offsetY) / density,
207
+ x:
208
+ Platform.OS === 'ios'
209
+ ? (point.x * scale - offsetX) / density
210
+ : (point.x * scale + offsetX) / density,
211
+ y:
212
+ Platform.OS === 'ios'
213
+ ? (point.y * scale - offsetY) / density
214
+ : (point.y * scale + offsetY) / density,
200
215
  });
201
216
 
202
217
  return {