react-native-rectangle-doc-scanner 0.23.0 → 0.25.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.
@@ -123,10 +123,16 @@ const DocScanner = ({ onCapture, overlayColor = '#e7a649', autoCapture = true, m
123
123
  console.log('[DocScanner] stage', stage);
124
124
  }
125
125
  }, []);
126
+ const [frameSize, setFrameSize] = (0, react_1.useState)(null);
127
+ const updateFrameSize = (0, react_native_worklets_core_1.useRunOnJS)((width, height) => {
128
+ setFrameSize({ width, height });
129
+ }, []);
126
130
  const frameProcessor = (0, react_native_vision_camera_1.useFrameProcessor)((frame) => {
127
131
  'worklet';
128
132
  let step = 'start';
129
133
  try {
134
+ // Report frame size for coordinate transformation
135
+ updateFrameSize(frame.width, frame.height);
130
136
  const ratio = 480 / frame.width;
131
137
  const width = Math.floor(frame.width * ratio);
132
138
  const height = Math.floor(frame.height * ratio);
@@ -314,7 +320,7 @@ const DocScanner = ({ onCapture, overlayColor = '#e7a649', autoCapture = true, m
314
320
  }
315
321
  return (react_1.default.createElement(react_native_1.View, { style: { flex: 1 } },
316
322
  react_1.default.createElement(react_native_vision_camera_1.Camera, { ref: handleCameraRef, style: react_native_1.StyleSheet.absoluteFillObject, device: resolvedDevice, isActive: true, photo: true, frameProcessor: frameProcessor, frameProcessorFps: 15, ...cameraRestProps }),
317
- react_1.default.createElement(overlay_1.Overlay, { quad: quad, color: overlayColor }),
323
+ react_1.default.createElement(overlay_1.Overlay, { quad: quad, color: overlayColor, frameSize: frameSize }),
318
324
  !autoCapture && (react_1.default.createElement(react_native_1.TouchableOpacity, { style: styles.button, onPress: async () => {
319
325
  if (!camera.current) {
320
326
  return;
@@ -3,6 +3,10 @@ import type { Point } from '../types';
3
3
  type OverlayProps = {
4
4
  quad: Point[] | null;
5
5
  color?: string;
6
+ frameSize: {
7
+ width: number;
8
+ height: number;
9
+ } | null;
6
10
  };
7
11
  export declare const Overlay: React.FC<OverlayProps>;
8
12
  export {};
@@ -37,28 +37,59 @@ exports.Overlay = void 0;
37
37
  const react_1 = __importStar(require("react"));
38
38
  const react_native_1 = require("react-native");
39
39
  const react_native_skia_1 = require("@shopify/react-native-skia");
40
- const Overlay = ({ quad, color = '#e7a649' }) => {
40
+ const Overlay = ({ quad, color = '#e7a649', frameSize }) => {
41
+ const { width: screenWidth, height: screenHeight } = (0, react_native_1.useWindowDimensions)();
41
42
  const path = (0, react_1.useMemo)(() => {
42
- if (!quad) {
43
+ if (!quad || !frameSize) {
43
44
  if (__DEV__) {
44
- console.log('[Overlay] no quad');
45
+ console.log('[Overlay] no quad or frameSize', { quad, frameSize });
45
46
  }
46
47
  return null;
47
48
  }
48
49
  if (__DEV__) {
49
50
  console.log('[Overlay] drawing quad:', quad);
50
51
  console.log('[Overlay] color:', color);
52
+ console.log('[Overlay] screen dimensions:', screenWidth, 'x', screenHeight);
53
+ console.log('[Overlay] frame dimensions:', frameSize.width, 'x', frameSize.height);
54
+ }
55
+ // Transform coordinates from camera frame space to screen space
56
+ const scaleX = screenWidth / frameSize.width;
57
+ const scaleY = screenHeight / frameSize.height;
58
+ if (__DEV__) {
59
+ console.log('[Overlay] scale factors:', scaleX, 'x', scaleY);
60
+ }
61
+ const transformedQuad = quad.map((p) => ({
62
+ x: p.x * scaleX,
63
+ y: p.y * scaleY,
64
+ }));
65
+ if (__DEV__) {
66
+ console.log('[Overlay] transformed quad:', transformedQuad);
51
67
  }
52
68
  const skPath = react_native_skia_1.Skia.Path.Make();
53
- skPath.moveTo(quad[0].x, quad[0].y);
54
- quad.slice(1).forEach((p) => skPath.lineTo(p.x, p.y));
69
+ skPath.moveTo(transformedQuad[0].x, transformedQuad[0].y);
70
+ transformedQuad.slice(1).forEach((p) => skPath.lineTo(p.x, p.y));
55
71
  skPath.close();
56
72
  return skPath;
57
- }, [quad, color]);
73
+ }, [quad, color, screenWidth, screenHeight, frameSize]);
74
+ // Test path - always visible for debugging
75
+ const testPath = (0, react_1.useMemo)(() => {
76
+ const tp = react_native_skia_1.Skia.Path.Make();
77
+ tp.moveTo(100, 100);
78
+ tp.lineTo(300, 100);
79
+ tp.lineTo(300, 300);
80
+ tp.lineTo(100, 300);
81
+ tp.close();
82
+ return tp;
83
+ }, []);
84
+ if (__DEV__) {
85
+ console.log('[Overlay] rendering Canvas with dimensions:', screenWidth, 'x', screenHeight);
86
+ }
58
87
  return (react_1.default.createElement(react_native_1.View, { style: styles.container, pointerEvents: "none" },
59
- react_1.default.createElement(react_native_skia_1.Canvas, { style: styles.canvas }, path && (react_1.default.createElement(react_1.default.Fragment, null,
60
- react_1.default.createElement(react_native_skia_1.Path, { path: path, color: color, style: "stroke", strokeWidth: 8 }),
61
- react_1.default.createElement(react_native_skia_1.Path, { path: path, color: "rgba(231, 166, 73, 0.2)", style: "fill" }))))));
88
+ react_1.default.createElement(react_native_skia_1.Canvas, { style: { width: screenWidth, height: screenHeight } },
89
+ react_1.default.createElement(react_native_skia_1.Path, { path: testPath, color: "red", style: "stroke", strokeWidth: 4 }),
90
+ path && (react_1.default.createElement(react_1.default.Fragment, null,
91
+ react_1.default.createElement(react_native_skia_1.Path, { path: path, color: color, style: "stroke", strokeWidth: 8 }),
92
+ react_1.default.createElement(react_native_skia_1.Path, { path: path, color: "rgba(231, 166, 73, 0.2)", style: "fill" }))))));
62
93
  };
63
94
  exports.Overlay = Overlay;
64
95
  const styles = react_native_1.StyleSheet.create({
@@ -69,7 +100,4 @@ const styles = react_native_1.StyleSheet.create({
69
100
  right: 0,
70
101
  bottom: 0,
71
102
  },
72
- canvas: {
73
- flex: 1,
74
- },
75
103
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-rectangle-doc-scanner",
3
- "version": "0.23.0",
3
+ "version": "0.25.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "repository": {
@@ -133,12 +133,20 @@ export const DocScanner: React.FC<Props> = ({
133
133
  }
134
134
  }, []);
135
135
 
136
+ const [frameSize, setFrameSize] = useState<{ width: number; height: number } | null>(null);
137
+ const updateFrameSize = useRunOnJS((width: number, height: number) => {
138
+ setFrameSize({ width, height });
139
+ }, []);
140
+
136
141
  const frameProcessor = useFrameProcessor((frame) => {
137
142
  'worklet';
138
143
 
139
144
  let step = 'start';
140
145
 
141
146
  try {
147
+ // Report frame size for coordinate transformation
148
+ updateFrameSize(frame.width, frame.height);
149
+
142
150
  const ratio = 480 / frame.width;
143
151
  const width = Math.floor(frame.width * ratio);
144
152
  const height = Math.floor(frame.height * ratio);
@@ -369,7 +377,7 @@ export const DocScanner: React.FC<Props> = ({
369
377
  frameProcessorFps={15}
370
378
  {...cameraRestProps}
371
379
  />
372
- <Overlay quad={quad} color={overlayColor} />
380
+ <Overlay quad={quad} color={overlayColor} frameSize={frameSize} />
373
381
  {!autoCapture && (
374
382
  <TouchableOpacity
375
383
  style={styles.button}
@@ -1,18 +1,21 @@
1
1
  import React, { useMemo } from 'react';
2
- import { View, StyleSheet } from 'react-native';
2
+ import { View, StyleSheet, useWindowDimensions } from 'react-native';
3
3
  import { Canvas, Path, Skia } from '@shopify/react-native-skia';
4
4
  import type { Point } from '../types';
5
5
 
6
6
  type OverlayProps = {
7
7
  quad: Point[] | null;
8
8
  color?: string;
9
+ frameSize: { width: number; height: number } | null;
9
10
  };
10
11
 
11
- export const Overlay: React.FC<OverlayProps> = ({ quad, color = '#e7a649' }) => {
12
+ export const Overlay: React.FC<OverlayProps> = ({ quad, color = '#e7a649', frameSize }) => {
13
+ const { width: screenWidth, height: screenHeight } = useWindowDimensions();
14
+
12
15
  const path = useMemo(() => {
13
- if (!quad) {
16
+ if (!quad || !frameSize) {
14
17
  if (__DEV__) {
15
- console.log('[Overlay] no quad');
18
+ console.log('[Overlay] no quad or frameSize', { quad, frameSize });
16
19
  }
17
20
  return null;
18
21
  }
@@ -20,18 +23,56 @@ export const Overlay: React.FC<OverlayProps> = ({ quad, color = '#e7a649' }) =>
20
23
  if (__DEV__) {
21
24
  console.log('[Overlay] drawing quad:', quad);
22
25
  console.log('[Overlay] color:', color);
26
+ console.log('[Overlay] screen dimensions:', screenWidth, 'x', screenHeight);
27
+ console.log('[Overlay] frame dimensions:', frameSize.width, 'x', frameSize.height);
28
+ }
29
+
30
+ // Transform coordinates from camera frame space to screen space
31
+ const scaleX = screenWidth / frameSize.width;
32
+ const scaleY = screenHeight / frameSize.height;
33
+
34
+ if (__DEV__) {
35
+ console.log('[Overlay] scale factors:', scaleX, 'x', scaleY);
36
+ }
37
+
38
+ const transformedQuad = quad.map((p) => ({
39
+ x: p.x * scaleX,
40
+ y: p.y * scaleY,
41
+ }));
42
+
43
+ if (__DEV__) {
44
+ console.log('[Overlay] transformed quad:', transformedQuad);
23
45
  }
24
46
 
25
47
  const skPath = Skia.Path.Make();
26
- skPath.moveTo(quad[0].x, quad[0].y);
27
- quad.slice(1).forEach((p) => skPath.lineTo(p.x, p.y));
48
+ skPath.moveTo(transformedQuad[0].x, transformedQuad[0].y);
49
+ transformedQuad.slice(1).forEach((p) => skPath.lineTo(p.x, p.y));
28
50
  skPath.close();
29
51
  return skPath;
30
- }, [quad, color]);
52
+ }, [quad, color, screenWidth, screenHeight, frameSize]);
53
+
54
+ // Test path - always visible for debugging
55
+ const testPath = useMemo(() => {
56
+ const tp = Skia.Path.Make();
57
+ tp.moveTo(100, 100);
58
+ tp.lineTo(300, 100);
59
+ tp.lineTo(300, 300);
60
+ tp.lineTo(100, 300);
61
+ tp.close();
62
+ return tp;
63
+ }, []);
64
+
65
+ if (__DEV__) {
66
+ console.log('[Overlay] rendering Canvas with dimensions:', screenWidth, 'x', screenHeight);
67
+ }
31
68
 
32
69
  return (
33
70
  <View style={styles.container} pointerEvents="none">
34
- <Canvas style={styles.canvas}>
71
+ <Canvas style={{ width: screenWidth, height: screenHeight }}>
72
+ {/* Debug: always show a test rectangle */}
73
+ <Path path={testPath} color="red" style="stroke" strokeWidth={4} />
74
+
75
+ {/* Actual quad overlay */}
35
76
  {path && (
36
77
  <>
37
78
  <Path path={path} color={color} style="stroke" strokeWidth={8} />
@@ -51,7 +92,4 @@ const styles = StyleSheet.create({
51
92
  right: 0,
52
93
  bottom: 0,
53
94
  },
54
- canvas: {
55
- flex: 1,
56
- },
57
95
  });