react-native-rectangle-doc-scanner 0.33.0 → 0.35.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.
@@ -196,25 +196,22 @@ const DocScanner = ({ onCapture, overlayColor = '#e7a649', autoCapture = true, m
196
196
  if (__DEV__) {
197
197
  console.log('[DocScanner] area', area, 'ratio', areaRatio);
198
198
  }
199
- if (areaRatio < 0.000005 || areaRatio > 0.995) {
199
+ // Skip if area ratio is too small or too large
200
+ if (areaRatio < 0.02 || areaRatio > 0.95) {
200
201
  continue;
201
202
  }
202
- // Use convex hull to simplify contour before polygon approximation
203
- const hull = react_native_fast_opencv_1.OpenCV.createObject(react_native_fast_opencv_1.ObjectType.PointVector);
204
- react_native_fast_opencv_1.OpenCV.invoke('convexHull', contour, hull);
205
203
  step = `contour_${i}_arcLength`;
206
204
  reportStage(step);
207
- const { value: perimeter } = react_native_fast_opencv_1.OpenCV.invoke('arcLength', hull, true);
205
+ const { value: perimeter } = react_native_fast_opencv_1.OpenCV.invoke('arcLength', contour, true);
208
206
  const approx = react_native_fast_opencv_1.OpenCV.createObject(react_native_fast_opencv_1.ObjectType.PointVector);
209
207
  let approxArray = [];
210
- // Start with smaller epsilon for more accurate corner detection
211
- // Try epsilon values from 0.4% up to 6% of perimeter
212
- const epsilonValues = [0.004, 0.006, 0.008, 0.01, 0.012, 0.015, 0.02, 0.03, 0.04, 0.05, 0.06];
208
+ // Try epsilon values from 0.2% to 8% of perimeter
209
+ const epsilonValues = [0.002, 0.004, 0.006, 0.008, 0.01, 0.015, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08];
213
210
  for (let attempt = 0; attempt < epsilonValues.length; attempt += 1) {
214
211
  const epsilon = epsilonValues[attempt] * perimeter;
215
212
  step = `contour_${i}_approxPolyDP_attempt_${attempt}`;
216
213
  reportStage(step);
217
- react_native_fast_opencv_1.OpenCV.invoke('approxPolyDP', hull, approx, epsilon, true);
214
+ react_native_fast_opencv_1.OpenCV.invoke('approxPolyDP', contour, approx, epsilon, true);
218
215
  step = `contour_${i}_toJS_attempt_${attempt}`;
219
216
  reportStage(step);
220
217
  const approxValue = react_native_fast_opencv_1.OpenCV.toJSValue(approx);
@@ -227,40 +224,7 @@ const DocScanner = ({ onCapture, overlayColor = '#e7a649', autoCapture = true, m
227
224
  break;
228
225
  }
229
226
  }
230
- if (approxArray.length !== 4) {
231
- // fallback: rotated rectangle using minAreaRect
232
- try {
233
- const rect = react_native_fast_opencv_1.OpenCV.invoke('minAreaRect', contour);
234
- const rectValue = rect?.value ?? rect;
235
- const centerX = rectValue.centerX ?? rectValue.center?.x ?? 0;
236
- const centerY = rectValue.centerY ?? rectValue.center?.y ?? 0;
237
- const rectW = rectValue.width ?? rectValue.size?.width ?? 0;
238
- const rectH = rectValue.height ?? rectValue.size?.height ?? 0;
239
- const angleDeg = rectValue.angle ?? rectValue.rotation ?? 0;
240
- if (rectW > 0 && rectH > 0) {
241
- const angleRad = (angleDeg * Math.PI) / 180;
242
- const cosA = Math.cos(angleRad);
243
- const sinA = Math.sin(angleRad);
244
- const halfW = rectW / 2;
245
- const halfH = rectH / 2;
246
- approxArray = [
247
- { x: centerX - halfW * cosA + halfH * sinA, y: centerY - halfW * sinA - halfH * cosA },
248
- { x: centerX + halfW * cosA + halfH * sinA, y: centerY + halfW * sinA - halfH * cosA },
249
- { x: centerX + halfW * cosA - halfH * sinA, y: centerY + halfW * sinA + halfH * cosA },
250
- { x: centerX - halfW * cosA - halfH * sinA, y: centerY - halfW * sinA + halfH * cosA },
251
- ];
252
- if (__DEV__) {
253
- console.log('[DocScanner] minAreaRect fallback', rectValue, approxArray);
254
- }
255
- }
256
- }
257
- catch (err) {
258
- if (__DEV__) {
259
- console.warn('[DocScanner] minAreaRect fallback failed', err);
260
- }
261
- }
262
- }
263
- // Only proceed if we found exactly 4 corners after fallback
227
+ // Only proceed if we found exactly 4 corners
264
228
  if (approxArray.length !== 4) {
265
229
  continue;
266
230
  }
@@ -95,25 +95,13 @@ const Overlay = ({ quad, color = '#e7a649', frameSize }) => {
95
95
  skPath.close();
96
96
  return skPath;
97
97
  }, [quad, color, screenWidth, screenHeight, frameSize]);
98
- // Test path - always visible for debugging
99
- const testPath = (0, react_1.useMemo)(() => {
100
- const tp = react_native_skia_1.Skia.Path.Make();
101
- tp.moveTo(100, 100);
102
- tp.lineTo(300, 100);
103
- tp.lineTo(300, 300);
104
- tp.lineTo(100, 300);
105
- tp.close();
106
- return tp;
107
- }, []);
108
98
  if (__DEV__) {
109
99
  console.log('[Overlay] rendering Canvas with dimensions:', screenWidth, 'x', screenHeight);
110
100
  }
111
101
  return (react_1.default.createElement(react_native_1.View, { style: styles.container, pointerEvents: "none" },
112
- react_1.default.createElement(react_native_skia_1.Canvas, { style: { width: screenWidth, height: screenHeight } },
113
- react_1.default.createElement(react_native_skia_1.Path, { path: testPath, color: "red", style: "stroke", strokeWidth: 4 }),
114
- path && (react_1.default.createElement(react_1.default.Fragment, null,
115
- react_1.default.createElement(react_native_skia_1.Path, { path: path, color: color, style: "stroke", strokeWidth: 8 }),
116
- react_1.default.createElement(react_native_skia_1.Path, { path: path, color: "rgba(231, 166, 73, 0.2)", style: "fill" }))))));
102
+ react_1.default.createElement(react_native_skia_1.Canvas, { style: { width: screenWidth, height: screenHeight } }, path && (react_1.default.createElement(react_1.default.Fragment, null,
103
+ react_1.default.createElement(react_native_skia_1.Path, { path: path, color: color, style: "stroke", strokeWidth: 8 }),
104
+ react_1.default.createElement(react_native_skia_1.Path, { path: path, color: "rgba(231, 166, 73, 0.2)", style: "fill" }))))));
117
105
  };
118
106
  exports.Overlay = Overlay;
119
107
  const styles = react_native_1.StyleSheet.create({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-rectangle-doc-scanner",
3
- "version": "0.33.0",
3
+ "version": "0.35.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "repository": {
@@ -224,30 +224,26 @@ export const DocScanner: React.FC<Props> = ({
224
224
  console.log('[DocScanner] area', area, 'ratio', areaRatio);
225
225
  }
226
226
 
227
- if (areaRatio < 0.000005 || areaRatio > 0.995) {
227
+ // Skip if area ratio is too small or too large
228
+ if (areaRatio < 0.02 || areaRatio > 0.95) {
228
229
  continue;
229
230
  }
230
231
 
231
- // Use convex hull to simplify contour before polygon approximation
232
- const hull = OpenCV.createObject(ObjectType.PointVector);
233
- OpenCV.invoke('convexHull', contour, hull);
234
-
235
232
  step = `contour_${i}_arcLength`;
236
233
  reportStage(step);
237
- const { value: perimeter } = OpenCV.invoke('arcLength', hull, true);
234
+ const { value: perimeter } = OpenCV.invoke('arcLength', contour, true);
238
235
  const approx = OpenCV.createObject(ObjectType.PointVector);
239
236
 
240
237
  let approxArray: Array<{ x: number; y: number }> = [];
241
238
 
242
- // Start with smaller epsilon for more accurate corner detection
243
- // Try epsilon values from 0.4% up to 6% of perimeter
244
- const epsilonValues = [0.004, 0.006, 0.008, 0.01, 0.012, 0.015, 0.02, 0.03, 0.04, 0.05, 0.06];
239
+ // Try epsilon values from 0.2% to 8% of perimeter
240
+ const epsilonValues = [0.002, 0.004, 0.006, 0.008, 0.01, 0.015, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08];
245
241
 
246
242
  for (let attempt = 0; attempt < epsilonValues.length; attempt += 1) {
247
243
  const epsilon = epsilonValues[attempt] * perimeter;
248
244
  step = `contour_${i}_approxPolyDP_attempt_${attempt}`;
249
245
  reportStage(step);
250
- OpenCV.invoke('approxPolyDP', hull, approx, epsilon, true);
246
+ OpenCV.invoke('approxPolyDP', contour, approx, epsilon, true);
251
247
 
252
248
  step = `contour_${i}_toJS_attempt_${attempt}`;
253
249
  reportStage(step);
@@ -264,44 +260,7 @@ export const DocScanner: React.FC<Props> = ({
264
260
  }
265
261
  }
266
262
 
267
- if (approxArray.length !== 4) {
268
- // fallback: rotated rectangle using minAreaRect
269
- try {
270
- const rect = OpenCV.invoke('minAreaRect', contour);
271
- const rectValue = rect?.value ?? rect;
272
-
273
- const centerX = rectValue.centerX ?? rectValue.center?.x ?? 0;
274
- const centerY = rectValue.centerY ?? rectValue.center?.y ?? 0;
275
- const rectW = rectValue.width ?? rectValue.size?.width ?? 0;
276
- const rectH = rectValue.height ?? rectValue.size?.height ?? 0;
277
- const angleDeg = rectValue.angle ?? rectValue.rotation ?? 0;
278
-
279
- if (rectW > 0 && rectH > 0) {
280
- const angleRad = (angleDeg * Math.PI) / 180;
281
- const cosA = Math.cos(angleRad);
282
- const sinA = Math.sin(angleRad);
283
- const halfW = rectW / 2;
284
- const halfH = rectH / 2;
285
-
286
- approxArray = [
287
- { x: centerX - halfW * cosA + halfH * sinA, y: centerY - halfW * sinA - halfH * cosA },
288
- { x: centerX + halfW * cosA + halfH * sinA, y: centerY + halfW * sinA - halfH * cosA },
289
- { x: centerX + halfW * cosA - halfH * sinA, y: centerY + halfW * sinA + halfH * cosA },
290
- { x: centerX - halfW * cosA - halfH * sinA, y: centerY - halfW * sinA + halfH * cosA },
291
- ];
292
-
293
- if (__DEV__) {
294
- console.log('[DocScanner] minAreaRect fallback', rectValue, approxArray);
295
- }
296
- }
297
- } catch (err) {
298
- if (__DEV__) {
299
- console.warn('[DocScanner] minAreaRect fallback failed', err);
300
- }
301
- }
302
- }
303
-
304
- // Only proceed if we found exactly 4 corners after fallback
263
+ // Only proceed if we found exactly 4 corners
305
264
  if (approxArray.length !== 4) {
306
265
  continue;
307
266
  }
@@ -79,17 +79,6 @@ export const Overlay: React.FC<OverlayProps> = ({ quad, color = '#e7a649', frame
79
79
  return skPath;
80
80
  }, [quad, color, screenWidth, screenHeight, frameSize]);
81
81
 
82
- // Test path - always visible for debugging
83
- const testPath = useMemo(() => {
84
- const tp = Skia.Path.Make();
85
- tp.moveTo(100, 100);
86
- tp.lineTo(300, 100);
87
- tp.lineTo(300, 300);
88
- tp.lineTo(100, 300);
89
- tp.close();
90
- return tp;
91
- }, []);
92
-
93
82
  if (__DEV__) {
94
83
  console.log('[Overlay] rendering Canvas with dimensions:', screenWidth, 'x', screenHeight);
95
84
  }
@@ -97,10 +86,6 @@ export const Overlay: React.FC<OverlayProps> = ({ quad, color = '#e7a649', frame
97
86
  return (
98
87
  <View style={styles.container} pointerEvents="none">
99
88
  <Canvas style={{ width: screenWidth, height: screenHeight }}>
100
- {/* Debug: always show a test rectangle */}
101
- <Path path={testPath} color="red" style="stroke" strokeWidth={4} />
102
-
103
- {/* Actual quad overlay */}
104
89
  {path && (
105
90
  <>
106
91
  <Path path={path} color={color} style="stroke" strokeWidth={8} />