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.
- package/android/src/camera2/kotlin/com/reactnativerectangledocscanner/CameraController.kt +26 -7
- package/android/src/camera2/kotlin/com/reactnativerectangledocscanner/DocumentScannerView.kt +5 -5
- package/android/src/common/kotlin/com/reactnativerectangledocscanner/DocumentDetector.kt +5 -5
- package/dist/DocScanner.js +15 -5
- package/package.json +1 -1
- package/src/DocScanner.tsx +20 -5
|
@@ -355,7 +355,22 @@ class CameraController(
|
|
|
355
355
|
mlBox: android.graphics.Rect?
|
|
356
356
|
): Rectangle? {
|
|
357
357
|
return try {
|
|
358
|
-
|
|
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
|
-
//
|
|
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 *
|
|
437
|
-
point.y *
|
|
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
|
|
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.
|
|
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
|
|
package/android/src/camera2/kotlin/com/reactnativerectangledocscanner/DocumentScannerView.kt
CHANGED
|
@@ -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 =
|
|
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 = (
|
|
694
|
-
val offsetY = (
|
|
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
|
|
698
|
-
val y = (point.y
|
|
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 =
|
|
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 = (
|
|
432
|
-
val offsetY = (
|
|
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)
|
|
436
|
-
val y = (point.y * scale)
|
|
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())
|
package/dist/DocScanner.js
CHANGED
|
@@ -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 =
|
|
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 =
|
|
128
|
-
|
|
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:
|
|
131
|
-
|
|
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
package/src/DocScanner.tsx
CHANGED
|
@@ -188,15 +188,30 @@ const mapRectangleToView = (
|
|
|
188
188
|
): Rectangle => {
|
|
189
189
|
const viewWidthPx = viewWidth * density;
|
|
190
190
|
const viewHeightPx = viewHeight * density;
|
|
191
|
-
const scale =
|
|
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 =
|
|
195
|
-
|
|
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:
|
|
199
|
-
|
|
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 {
|