react-native-rectangle-doc-scanner 10.23.0 → 10.24.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/DocumentScannerView.kt
CHANGED
|
@@ -25,6 +25,7 @@ import kotlinx.coroutines.delay
|
|
|
25
25
|
import java.io.File
|
|
26
26
|
import kotlin.math.min
|
|
27
27
|
import kotlin.math.max
|
|
28
|
+
import kotlin.math.hypot
|
|
28
29
|
|
|
29
30
|
class DocumentScannerView(context: ThemedReactContext) : FrameLayout(context), LifecycleOwner {
|
|
30
31
|
private val themedContext = context
|
|
@@ -58,6 +59,7 @@ class DocumentScannerView(context: ThemedReactContext) : FrameLayout(context), L
|
|
|
58
59
|
private var lastDetectedImageWidth = 0
|
|
59
60
|
private var lastDetectedImageHeight = 0
|
|
60
61
|
private var lastRectangleOnScreen: Rectangle? = null
|
|
62
|
+
private var lastSmoothedRectangleOnScreen: Rectangle? = null
|
|
61
63
|
|
|
62
64
|
// Coroutine scope for async operations
|
|
63
65
|
private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
|
|
@@ -215,19 +217,82 @@ class DocumentScannerView(context: ThemedReactContext) : FrameLayout(context), L
|
|
|
215
217
|
} else {
|
|
216
218
|
null
|
|
217
219
|
}
|
|
218
|
-
|
|
220
|
+
val smoothedRectangleOnScreen = smoothRectangle(rectangleOnScreen, width, height)
|
|
221
|
+
lastRectangleOnScreen = smoothedRectangleOnScreen
|
|
219
222
|
val quality = when {
|
|
220
|
-
|
|
221
|
-
DocumentDetector.evaluateRectangleQualityInView(
|
|
223
|
+
smoothedRectangleOnScreen != null && width > 0 && height > 0 ->
|
|
224
|
+
DocumentDetector.evaluateRectangleQualityInView(smoothedRectangleOnScreen, width, height)
|
|
222
225
|
rectangle != null -> DocumentDetector.evaluateRectangleQuality(rectangle, imageWidth, imageHeight)
|
|
223
226
|
else -> RectangleQuality.TOO_FAR
|
|
224
227
|
}
|
|
225
228
|
|
|
226
229
|
post {
|
|
227
|
-
onRectangleDetected(
|
|
230
|
+
onRectangleDetected(smoothedRectangleOnScreen, rectangle, quality, imageWidth, imageHeight)
|
|
228
231
|
}
|
|
229
232
|
}
|
|
230
233
|
|
|
234
|
+
private fun smoothRectangle(rectangle: Rectangle?, viewWidth: Int, viewHeight: Int): Rectangle? {
|
|
235
|
+
if (rectangle == null || viewWidth <= 0 || viewHeight <= 0) {
|
|
236
|
+
lastSmoothedRectangleOnScreen = null
|
|
237
|
+
return null
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
val prev = lastSmoothedRectangleOnScreen
|
|
241
|
+
if (prev == null) {
|
|
242
|
+
lastSmoothedRectangleOnScreen = rectangle
|
|
243
|
+
return rectangle
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
val minDim = min(viewWidth, viewHeight).toDouble()
|
|
247
|
+
val snapThreshold = max(12.0, minDim * 0.015)
|
|
248
|
+
val smoothThreshold = max(24.0, minDim * 0.06)
|
|
249
|
+
val maxCornerDistance = max(
|
|
250
|
+
maxCornerDistance(prev, rectangle),
|
|
251
|
+
maxCornerDistance(rectangle, prev)
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
val result = when {
|
|
255
|
+
maxCornerDistance <= snapThreshold -> prev
|
|
256
|
+
maxCornerDistance <= smoothThreshold -> blendRectangle(prev, rectangle, 0.35)
|
|
257
|
+
else -> rectangle
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
lastSmoothedRectangleOnScreen = result
|
|
261
|
+
return result
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
private fun maxCornerDistance(a: Rectangle, b: Rectangle): Double {
|
|
265
|
+
return max(
|
|
266
|
+
max(
|
|
267
|
+
distance(a.topLeft, b.topLeft),
|
|
268
|
+
distance(a.topRight, b.topRight)
|
|
269
|
+
),
|
|
270
|
+
max(
|
|
271
|
+
distance(a.bottomLeft, b.bottomLeft),
|
|
272
|
+
distance(a.bottomRight, b.bottomRight)
|
|
273
|
+
)
|
|
274
|
+
)
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
private fun distance(p1: Point, p2: Point): Double {
|
|
278
|
+
return hypot(p1.x - p2.x, p1.y - p2.y)
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
private fun blendRectangle(a: Rectangle, b: Rectangle, t: Double): Rectangle {
|
|
282
|
+
fun lerp(p1: Point, p2: Point): Point {
|
|
283
|
+
val x = p1.x + (p2.x - p1.x) * t
|
|
284
|
+
val y = p1.y + (p2.y - p1.y) * t
|
|
285
|
+
return Point(x, y)
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return Rectangle(
|
|
289
|
+
lerp(a.topLeft, b.topLeft),
|
|
290
|
+
lerp(a.topRight, b.topRight),
|
|
291
|
+
lerp(a.bottomLeft, b.bottomLeft),
|
|
292
|
+
lerp(a.bottomRight, b.bottomRight)
|
|
293
|
+
)
|
|
294
|
+
}
|
|
295
|
+
|
|
231
296
|
private fun onRectangleDetected(
|
|
232
297
|
rectangleOnScreen: Rectangle?,
|
|
233
298
|
rectangleCoordinates: Rectangle?,
|
package/package.json
CHANGED