react-native-rectangle-doc-scanner 0.18.0 → 0.20.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/dist/DocScanner.js +44 -17
- package/dist/utils/overlay.js +6 -0
- package/package.json +1 -1
- package/src/DocScanner.tsx +46 -20
- package/src/utils/overlay.tsx +7 -0
package/dist/DocScanner.js
CHANGED
|
@@ -43,26 +43,40 @@ const react_native_fast_opencv_1 = require("react-native-fast-opencv");
|
|
|
43
43
|
const overlay_1 = require("./utils/overlay");
|
|
44
44
|
const stability_1 = require("./utils/stability");
|
|
45
45
|
const isConvexQuadrilateral = (points) => {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
let previous = 0;
|
|
50
|
-
for (let i = 0; i < 4; i++) {
|
|
51
|
-
const p0 = points[i];
|
|
52
|
-
const p1 = points[(i + 1) % 4];
|
|
53
|
-
const p2 = points[(i + 2) % 4];
|
|
54
|
-
const cross = (p1.x - p0.x) * (p2.y - p1.y) - (p1.y - p0.y) * (p2.x - p1.x);
|
|
55
|
-
if (Math.abs(cross) < 1e-3) {
|
|
46
|
+
'worklet';
|
|
47
|
+
try {
|
|
48
|
+
if (points.length !== 4) {
|
|
56
49
|
return false;
|
|
57
50
|
}
|
|
58
|
-
|
|
59
|
-
|
|
51
|
+
// Validate all points have valid x and y
|
|
52
|
+
for (const p of points) {
|
|
53
|
+
if (typeof p.x !== 'number' || typeof p.y !== 'number' ||
|
|
54
|
+
!isFinite(p.x) || !isFinite(p.y)) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
60
57
|
}
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
let previous = 0;
|
|
59
|
+
for (let i = 0; i < 4; i++) {
|
|
60
|
+
const p0 = points[i];
|
|
61
|
+
const p1 = points[(i + 1) % 4];
|
|
62
|
+
const p2 = points[(i + 2) % 4];
|
|
63
|
+
const cross = (p1.x - p0.x) * (p2.y - p1.y) - (p1.y - p0.y) * (p2.x - p1.x);
|
|
64
|
+
// Relax the collinearity check - allow very small cross products
|
|
65
|
+
if (Math.abs(cross) < 0.1) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
if (i === 0) {
|
|
69
|
+
previous = cross;
|
|
70
|
+
}
|
|
71
|
+
else if (previous * cross < 0) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
63
74
|
}
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
return false;
|
|
64
79
|
}
|
|
65
|
-
return true;
|
|
66
80
|
};
|
|
67
81
|
const DocScanner = ({ onCapture, overlayColor = '#e7a649', autoCapture = true, minStableFrames = 8, cameraProps, children, }) => {
|
|
68
82
|
const device = (0, react_native_vision_camera_1.useCameraDevice)('back');
|
|
@@ -230,8 +244,21 @@ const DocScanner = ({ onCapture, overlayColor = '#e7a649', autoCapture = true, m
|
|
|
230
244
|
y: pt.y / ratio,
|
|
231
245
|
}));
|
|
232
246
|
// Skip convexity check for boundingRect (always forms a valid rectangle)
|
|
233
|
-
if (!usedBoundingRect
|
|
234
|
-
|
|
247
|
+
if (!usedBoundingRect) {
|
|
248
|
+
try {
|
|
249
|
+
if (!isConvexQuadrilateral(points)) {
|
|
250
|
+
if (__DEV__) {
|
|
251
|
+
console.log('[DocScanner] not convex, skipping:', points);
|
|
252
|
+
}
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
catch (err) {
|
|
257
|
+
if (__DEV__) {
|
|
258
|
+
console.warn('[DocScanner] convex check error:', err, 'points:', points);
|
|
259
|
+
}
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
235
262
|
}
|
|
236
263
|
if (area > maxArea) {
|
|
237
264
|
best = points;
|
package/dist/utils/overlay.js
CHANGED
|
@@ -39,8 +39,14 @@ const react_native_skia_1 = require("@shopify/react-native-skia");
|
|
|
39
39
|
const Overlay = ({ quad, color = '#e7a649' }) => {
|
|
40
40
|
const path = (0, react_1.useMemo)(() => {
|
|
41
41
|
if (!quad) {
|
|
42
|
+
if (__DEV__) {
|
|
43
|
+
console.log('[Overlay] no quad');
|
|
44
|
+
}
|
|
42
45
|
return null;
|
|
43
46
|
}
|
|
47
|
+
if (__DEV__) {
|
|
48
|
+
console.log('[Overlay] drawing quad:', quad);
|
|
49
|
+
}
|
|
44
50
|
const skPath = react_native_skia_1.Skia.Path.Make();
|
|
45
51
|
skPath.moveTo(quad[0].x, quad[0].y);
|
|
46
52
|
quad.slice(1).forEach((p) => skPath.lineTo(p.x, p.y));
|
package/package.json
CHANGED
package/src/DocScanner.tsx
CHANGED
|
@@ -17,30 +17,44 @@ import { checkStability } from './utils/stability';
|
|
|
17
17
|
import type { Point } from './types';
|
|
18
18
|
|
|
19
19
|
const isConvexQuadrilateral = (points: Point[]) => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
'worklet';
|
|
21
|
+
try {
|
|
22
|
+
if (points.length !== 4) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Validate all points have valid x and y
|
|
27
|
+
for (const p of points) {
|
|
28
|
+
if (typeof p.x !== 'number' || typeof p.y !== 'number' ||
|
|
29
|
+
!isFinite(p.x) || !isFinite(p.y)) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
23
33
|
|
|
24
|
-
|
|
34
|
+
let previous = 0;
|
|
25
35
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
36
|
+
for (let i = 0; i < 4; i++) {
|
|
37
|
+
const p0 = points[i];
|
|
38
|
+
const p1 = points[(i + 1) % 4];
|
|
39
|
+
const p2 = points[(i + 2) % 4];
|
|
40
|
+
const cross = (p1.x - p0.x) * (p2.y - p1.y) - (p1.y - p0.y) * (p2.x - p1.x);
|
|
31
41
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
42
|
+
// Relax the collinearity check - allow very small cross products
|
|
43
|
+
if (Math.abs(cross) < 0.1) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
35
46
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
47
|
+
if (i === 0) {
|
|
48
|
+
previous = cross;
|
|
49
|
+
} else if (previous * cross < 0) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
40
52
|
}
|
|
41
|
-
}
|
|
42
53
|
|
|
43
|
-
|
|
54
|
+
return true;
|
|
55
|
+
} catch (err) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
44
58
|
};
|
|
45
59
|
|
|
46
60
|
type CameraRef = {
|
|
@@ -267,8 +281,20 @@ export const DocScanner: React.FC<Props> = ({
|
|
|
267
281
|
}));
|
|
268
282
|
|
|
269
283
|
// Skip convexity check for boundingRect (always forms a valid rectangle)
|
|
270
|
-
if (!usedBoundingRect
|
|
271
|
-
|
|
284
|
+
if (!usedBoundingRect) {
|
|
285
|
+
try {
|
|
286
|
+
if (!isConvexQuadrilateral(points)) {
|
|
287
|
+
if (__DEV__) {
|
|
288
|
+
console.log('[DocScanner] not convex, skipping:', points);
|
|
289
|
+
}
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
} catch (err) {
|
|
293
|
+
if (__DEV__) {
|
|
294
|
+
console.warn('[DocScanner] convex check error:', err, 'points:', points);
|
|
295
|
+
}
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
272
298
|
}
|
|
273
299
|
|
|
274
300
|
if (area > maxArea) {
|
package/src/utils/overlay.tsx
CHANGED
|
@@ -10,9 +10,16 @@ type OverlayProps = {
|
|
|
10
10
|
export const Overlay: React.FC<OverlayProps> = ({ quad, color = '#e7a649' }) => {
|
|
11
11
|
const path = useMemo(() => {
|
|
12
12
|
if (!quad) {
|
|
13
|
+
if (__DEV__) {
|
|
14
|
+
console.log('[Overlay] no quad');
|
|
15
|
+
}
|
|
13
16
|
return null;
|
|
14
17
|
}
|
|
15
18
|
|
|
19
|
+
if (__DEV__) {
|
|
20
|
+
console.log('[Overlay] drawing quad:', quad);
|
|
21
|
+
}
|
|
22
|
+
|
|
16
23
|
const skPath = Skia.Path.Make();
|
|
17
24
|
skPath.moveTo(quad[0].x, quad[0].y);
|
|
18
25
|
quad.slice(1).forEach((p) => skPath.lineTo(p.x, p.y));
|