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.
@@ -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
- if (points.length !== 4) {
47
- return false;
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
- if (i === 0) {
59
- previous = cross;
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
- else if (previous * cross < 0) {
62
- return false;
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 && !isConvexQuadrilateral(points)) {
234
- continue;
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;
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-rectangle-doc-scanner",
3
- "version": "0.18.0",
3
+ "version": "0.20.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "repository": {
@@ -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
- if (points.length !== 4) {
21
- return false;
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
- let previous = 0;
34
+ let previous = 0;
25
35
 
26
- for (let i = 0; i < 4; i++) {
27
- const p0 = points[i];
28
- const p1 = points[(i + 1) % 4];
29
- const p2 = points[(i + 2) % 4];
30
- const cross = (p1.x - p0.x) * (p2.y - p1.y) - (p1.y - p0.y) * (p2.x - p1.x);
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
- if (Math.abs(cross) < 1e-3) {
33
- return false;
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
- if (i === 0) {
37
- previous = cross;
38
- } else if (previous * cross < 0) {
39
- return false;
47
+ if (i === 0) {
48
+ previous = cross;
49
+ } else if (previous * cross < 0) {
50
+ return false;
51
+ }
40
52
  }
41
- }
42
53
 
43
- return true;
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 && !isConvexQuadrilateral(points)) {
271
- continue;
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) {
@@ -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));