react-native-expo-cropper 1.0.26 → 1.0.27

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-expo-cropper",
3
- "version": "1.0.26",
3
+ "version": "1.0.27",
4
4
  "description": "Recadrage polygonal d'images.",
5
5
  "main": "index.js",
6
6
  "author": "PCS AGRI",
@@ -79,6 +79,53 @@ const ImageCropper = ({ onConfirm, openCameraFirst, initialImage ,addheight}) =>
79
79
  return () => { cancelled = true; };
80
80
  }, [captureRequested, showResult, overlayReady, addheight, onConfirm]);
81
81
 
82
+ // Helpers to compute crop rectangle in original image pixels
83
+ const getImageSizeAsync = (uri) =>
84
+ new Promise((resolve, reject) => {
85
+ Image.getSize(uri, (w, h) => resolve({ width: w, height: h }), reject);
86
+ });
87
+
88
+ const computeCropRect = (pts, measure, origW, origH) => {
89
+ const containerW = measure.width;
90
+ const containerH = measure.height;
91
+ if (!containerW || !containerH || !origW || !origH || !pts || pts.length === 0) return null;
92
+
93
+ const ratio = origH / origW;
94
+ let dispW, dispH, offX, offY;
95
+ if (containerW * ratio <= containerH) {
96
+ // image constrained by width
97
+ dispW = containerW;
98
+ dispH = containerW * ratio;
99
+ offX = 0;
100
+ offY = (containerH - dispH) / 2;
101
+ } else {
102
+ // image constrained by height
103
+ dispH = containerH;
104
+ dispW = containerH / ratio;
105
+ offY = 0;
106
+ offX = (containerW - dispW) / 2;
107
+ }
108
+
109
+ const xs = pts.map(p => Math.max(0, Math.min(dispW, p.x - offX)));
110
+ const ys = pts.map(p => Math.max(0, Math.min(dispH, p.y - offY)));
111
+ const minX = Math.min(...xs);
112
+ const maxX = Math.max(...xs);
113
+ const minY = Math.min(...ys);
114
+ const maxY = Math.max(...ys);
115
+
116
+ const normMinX = minX / dispW;
117
+ const normMaxX = maxX / dispW;
118
+ const normMinY = minY / dispH;
119
+ const normMaxY = maxY / dispH;
120
+
121
+ const originX = Math.round(normMinX * origW);
122
+ const originY = Math.round(normMinY * origH);
123
+ const widthPx = Math.round((normMaxX - normMinX) * origW);
124
+ const heightPx = Math.round((normMaxY - normMinY) * origH);
125
+
126
+ return { x: originX, y: originY, width: widthPx, height: heightPx };
127
+ };
128
+
82
129
 
83
130
  const initializeCropBox = () => {
84
131
  const { width, height } = imageMeasure.current;
@@ -143,26 +190,6 @@ const ImageCropper = ({ onConfirm, openCameraFirst, initialImage ,addheight}) =>
143
190
  const boundedX = Math.max(0, Math.min(moveX, width));
144
191
  const boundedY = Math.max(0, Math.min(moveY, height));
145
192
 
146
- const edgeThreshold = 10;
147
- const isNearTopOrBottomEdge =
148
- boundedY <= edgeThreshold || boundedY >= height - edgeThreshold;
149
-
150
- const isNearLeftOrRightEdge =
151
- boundedX <= edgeThreshold || boundedX >= width - edgeThreshold;
152
-
153
- if (isNearTopOrBottomEdge || isNearLeftOrRightEdge) {
154
- // Reset point to last known position
155
- if (lastValidPosition.current && selectedPointIndex.current !== null) {
156
- setPoints(prev =>
157
- prev.map((p, i) =>
158
- i === selectedPointIndex.current ? lastValidPosition.current : p
159
- )
160
- );
161
- }
162
- selectedPointIndex.current = null;
163
- return;
164
- }
165
-
166
193
  // Valid move — update point and store as new last valid position
167
194
  const updatedPoint = { x: boundedX, y: boundedY };
168
195
  lastValidPosition.current = updatedPoint;
@@ -288,35 +315,18 @@ const ImageCropper = ({ onConfirm, openCameraFirst, initialImage ,addheight}) =>
288
315
  <TouchableOpacity
289
316
  style={styles.button}
290
317
  onPress={async () => {
291
- setIsLoading(true);
292
- setShowResult(true);
293
- setOverlayReady(false);
294
- setCaptureRequested(true);
295
-
296
- if (Platform.OS === 'android') {
297
- try {
298
- await new Promise((resolve) => requestAnimationFrame(resolve));
299
- const capturedUri = await captureRef(viewRef.current, {
300
- format: 'png',
301
- quality: 1,
302
- });
303
- const enhancedUri = await enhanceImage(capturedUri, addheight);
304
- const name = `IMAGE XTK${Date.now()}.png`;
305
-
306
- if (onConfirm) {
307
- onConfirm(enhancedUri, name);
308
- }
309
-
310
- setShowResult(false);
311
- setIsLoading(false);
312
- setShowFullScreenCapture(false);
313
- setCaptureRequested(false);
314
- setOverlayReady(false);
315
- } catch (error) {
316
- console.error('Erreur lors de la capture :', error);
317
- alert('Erreur lors de la capture !');
318
- setIsLoading(false);
319
- }
318
+ try {
319
+ setIsLoading(true);
320
+ const { width: origW, height: origH } = await getImageSizeAsync(image);
321
+ const rect = computeCropRect(points, imageMeasure.current, origW, origH);
322
+ const enhancedUri = await enhanceImage(image, addheight, rect);
323
+ const name = `IMAGE XTK${Date.now()}.png`;
324
+ if (onConfirm) onConfirm(enhancedUri, name);
325
+ } catch (error) {
326
+ console.error('Erreur lors de la capture :', error);
327
+ alert('Erreur lors de la capture !');
328
+ } finally {
329
+ setIsLoading(false);
320
330
  }
321
331
  }}
322
332
  >
@@ -1,28 +1,45 @@
1
- import * as ImageManipulator from 'expo-image-manipulator';
2
-
3
- export const enhanceImage = async (uri , addheight) => {
4
- try {
5
- const imageInfo = await ImageManipulator.manipulateAsync(uri, []);
6
- const ratio = imageInfo.height / imageInfo.width;
7
-
8
- const maxHeight = addheight;
9
- const newWidth = Math.round(maxHeight / ratio);
10
- const newHeight = Math.round(newWidth * ratio);
11
-
12
- const result = await ImageManipulator.manipulateAsync(
13
- uri,
14
- [
15
- { resize: { width: newWidth, height: newHeight } },
16
- ],
17
- {
18
- compress: 1,
19
- format: ImageManipulator.SaveFormat.PNG
20
- }
21
- );
22
-
23
- return result.uri;
24
- } catch (error) {
25
- console.error("Erreur T404K:", error);
26
- return uri;
27
- }
1
+ import * as ImageManipulator from 'expo-image-manipulator';
2
+
3
+ // Crop the image to the provided rectangle (in original image pixels), then resize.
4
+ // cropRect: { x, y, width, height } in original image coordinates
5
+ export const enhanceImage = async (uri, addheight, cropRect) => {
6
+ try {
7
+ const actions = [];
8
+ if (cropRect && cropRect.width > 0 && cropRect.height > 0) {
9
+ actions.push({
10
+ crop: {
11
+ originX: Math.round(cropRect.x),
12
+ originY: Math.round(cropRect.y),
13
+ width: Math.round(cropRect.width),
14
+ height: Math.round(cropRect.height),
15
+ },
16
+ });
17
+ }
18
+
19
+ // First: crop (if requested)
20
+ const cropped = await ImageManipulator.manipulateAsync(uri, actions, {
21
+ compress: 1,
22
+ format: ImageManipulator.SaveFormat.PNG,
23
+ });
24
+
25
+ // Then: resize to requested height while preserving aspect ratio
26
+ const targetHeight = addheight || cropped.height;
27
+ const ratio = cropped.height / cropped.width;
28
+ const newWidth = Math.round(targetHeight / ratio);
29
+ const newHeight = Math.round(newWidth * ratio);
30
+
31
+ const result = await ImageManipulator.manipulateAsync(
32
+ cropped.uri,
33
+ [{ resize: { width: newWidth, height: newHeight } }],
34
+ {
35
+ compress: 1,
36
+ format: ImageManipulator.SaveFormat.PNG,
37
+ }
38
+ );
39
+
40
+ return result.uri;
41
+ } catch (error) {
42
+ console.error('Erreur T404K:', error);
43
+ return uri;
44
+ }
28
45
  };