react-native-expo-cropper 1.2.42 → 1.2.44
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/ImageCropper.js +28 -10
- package/package.json +1 -1
- package/src/ImageCropper.js +24 -9
package/dist/ImageCropper.js
CHANGED
|
@@ -445,13 +445,14 @@ var ImageCropper = function ImageCropper(_ref) {
|
|
|
445
445
|
var imageRectY = wrapper.y + imageRect.y;
|
|
446
446
|
|
|
447
447
|
// ✅ PRIORITY RULE #3: IF image comes from camera → Use EXACT green frame coordinates
|
|
448
|
-
// Image is displayed in "cover" mode (full wrapper), so green frame coords = white frame coords
|
|
448
|
+
// Image is displayed in "cover" mode (full wrapper), so green frame coords = white frame coords.
|
|
449
|
+
// Store points in WRAPPER-RELATIVE coordinates (greenFrame.x, greenFrame.y) so they match
|
|
450
|
+
// touch events (locationX/locationY are relative to the wrapper). This keeps display→image
|
|
451
|
+
// conversion correct in Confirm.
|
|
449
452
|
if (cameraFrameData.current && cameraFrameData.current.greenFrame && originalImageDimensions.current.width > 0) {
|
|
450
453
|
var greenFrame = cameraFrameData.current.greenFrame;
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
var _boxX = wrapper.x + greenFrame.x;
|
|
454
|
-
var _boxY = wrapper.y + greenFrame.y;
|
|
454
|
+
var _boxX = greenFrame.x;
|
|
455
|
+
var _boxY = greenFrame.y;
|
|
455
456
|
var _boxWidth = greenFrame.width;
|
|
456
457
|
var _boxHeight = greenFrame.height;
|
|
457
458
|
|
|
@@ -464,7 +465,7 @@ var ImageCropper = function ImageCropper(_ref) {
|
|
|
464
465
|
return;
|
|
465
466
|
}
|
|
466
467
|
|
|
467
|
-
// ✅
|
|
468
|
+
// ✅ Points in wrapper-relative coords (same as touch events)
|
|
468
469
|
var _newPoints = [{
|
|
469
470
|
x: _boxX,
|
|
470
471
|
y: _boxY
|
|
@@ -507,7 +508,7 @@ var ImageCropper = function ImageCropper(_ref) {
|
|
|
507
508
|
width: _boxWidth.toFixed(2),
|
|
508
509
|
height: _boxHeight.toFixed(2)
|
|
509
510
|
},
|
|
510
|
-
note: "
|
|
511
|
+
note: "Points in wrapper-relative coords - same as touch events and crop_image_size"
|
|
511
512
|
});
|
|
512
513
|
setPoints(_newPoints);
|
|
513
514
|
hasInitializedCropBox.current = true; // ✅ CRITICAL: Mark as initialized
|
|
@@ -1479,7 +1480,7 @@ var ImageCropper = function ImageCropper(_ref) {
|
|
|
1479
1480
|
}, "Reset")), /*#__PURE__*/_react["default"].createElement(_reactNative.TouchableOpacity, {
|
|
1480
1481
|
style: _ImageCropperStyles["default"].button,
|
|
1481
1482
|
onPress: /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
|
|
1482
|
-
var actualImageWidth, actualImageHeight, layout, contentRect, displayedWidth, displayedHeight,
|
|
1483
|
+
var _cameraFrameData$curr4, actualImageWidth, actualImageHeight, isCoverMode, captured, layout, contentRect, displayedWidth, displayedHeight, scale, coverOffsetX, coverOffsetY, scaledWidth, scaledHeight, originalUri, cropMeta, imagePoints, minX, minY, maxX, maxY, cropX, cropY, cropEndX, cropEndY, cropWidth, cropHeight, bbox, polygon, name, _t2;
|
|
1483
1484
|
return _regenerator().w(function (_context2) {
|
|
1484
1485
|
while (1) switch (_context2.p = _context2.n) {
|
|
1485
1486
|
case 0:
|
|
@@ -1487,7 +1488,25 @@ var ImageCropper = function ImageCropper(_ref) {
|
|
|
1487
1488
|
_context2.p = 1;
|
|
1488
1489
|
console.log("=== Starting pixel-perfect metadata export (no bitmap crop on mobile) ===");
|
|
1489
1490
|
actualImageWidth = originalImageDimensions.current.width;
|
|
1490
|
-
actualImageHeight = originalImageDimensions.current.height;
|
|
1491
|
+
actualImageHeight = originalImageDimensions.current.height; // ✅ CRITICAL: Camera JPEGs often have EXIF 6 (90° CW). The Image component displays
|
|
1492
|
+
// the EXIF-corrected view (3120×4160 portrait) but takePictureAsync returns raw (4160×3120).
|
|
1493
|
+
// Use swapped dimensions for coordinate conversion so bbox matches what the user sees.
|
|
1494
|
+
isCoverMode = !!(cameraFrameData.current && cameraFrameData.current.greenFrame);
|
|
1495
|
+
captured = (_cameraFrameData$curr4 = cameraFrameData.current) === null || _cameraFrameData$curr4 === void 0 ? void 0 : _cameraFrameData$curr4.capturedImageSize;
|
|
1496
|
+
if (isCoverMode && captured && captured.width > captured.height) {
|
|
1497
|
+
actualImageWidth = captured.height;
|
|
1498
|
+
actualImageHeight = captured.width;
|
|
1499
|
+
console.log("✅ Using EXIF-swapped dimensions for bbox (raw was landscape, display is portrait):", {
|
|
1500
|
+
raw: {
|
|
1501
|
+
w: captured.width,
|
|
1502
|
+
h: captured.height
|
|
1503
|
+
},
|
|
1504
|
+
display: {
|
|
1505
|
+
w: actualImageWidth,
|
|
1506
|
+
h: actualImageHeight
|
|
1507
|
+
}
|
|
1508
|
+
});
|
|
1509
|
+
}
|
|
1491
1510
|
if (!(actualImageWidth === 0 || actualImageHeight === 0)) {
|
|
1492
1511
|
_context2.n = 2;
|
|
1493
1512
|
break;
|
|
@@ -1523,7 +1542,6 @@ var ImageCropper = function ImageCropper(_ref) {
|
|
|
1523
1542
|
case 3:
|
|
1524
1543
|
throw new Error("Displayed image dimensions not available.");
|
|
1525
1544
|
case 4:
|
|
1526
|
-
isCoverMode = !!(cameraFrameData.current && cameraFrameData.current.greenFrame);
|
|
1527
1545
|
coverOffsetX = 0, coverOffsetY = 0;
|
|
1528
1546
|
if (isCoverMode) {
|
|
1529
1547
|
scale = Math.max(displayedWidth / actualImageWidth, displayedHeight / actualImageHeight);
|
package/package.json
CHANGED
package/src/ImageCropper.js
CHANGED
|
@@ -334,13 +334,15 @@ const ImageCropper = ({ onConfirm, openCameraFirst, initialImage, addheight, rot
|
|
|
334
334
|
const imageRectY = wrapper.y + imageRect.y;
|
|
335
335
|
|
|
336
336
|
// ✅ PRIORITY RULE #3: IF image comes from camera → Use EXACT green frame coordinates
|
|
337
|
-
// Image is displayed in "cover" mode (full wrapper), so green frame coords = white frame coords
|
|
337
|
+
// Image is displayed in "cover" mode (full wrapper), so green frame coords = white frame coords.
|
|
338
|
+
// Store points in WRAPPER-RELATIVE coordinates (greenFrame.x, greenFrame.y) so they match
|
|
339
|
+
// touch events (locationX/locationY are relative to the wrapper). This keeps display→image
|
|
340
|
+
// conversion correct in Confirm.
|
|
338
341
|
if (cameraFrameData.current && cameraFrameData.current.greenFrame && originalImageDimensions.current.width > 0) {
|
|
339
342
|
const greenFrame = cameraFrameData.current.greenFrame;
|
|
340
343
|
|
|
341
|
-
|
|
342
|
-
const
|
|
343
|
-
const boxY = wrapper.y + greenFrame.y;
|
|
344
|
+
const boxX = greenFrame.x;
|
|
345
|
+
const boxY = greenFrame.y;
|
|
344
346
|
const boxWidth = greenFrame.width;
|
|
345
347
|
const boxHeight = greenFrame.height;
|
|
346
348
|
|
|
@@ -353,7 +355,7 @@ const ImageCropper = ({ onConfirm, openCameraFirst, initialImage, addheight, rot
|
|
|
353
355
|
return;
|
|
354
356
|
}
|
|
355
357
|
|
|
356
|
-
// ✅
|
|
358
|
+
// ✅ Points in wrapper-relative coords (same as touch events)
|
|
357
359
|
const newPoints = [
|
|
358
360
|
{ x: boxX, y: boxY }, // Top-left
|
|
359
361
|
{ x: boxX + boxWidth, y: boxY }, // Top-right
|
|
@@ -371,7 +373,7 @@ const ImageCropper = ({ onConfirm, openCameraFirst, initialImage, addheight, rot
|
|
|
371
373
|
console.log("✅ Initializing crop box for camera image (COVER MODE - exact green frame):", {
|
|
372
374
|
greenFrame: { x: greenFrame.x, y: greenFrame.y, width: greenFrame.width, height: greenFrame.height },
|
|
373
375
|
whiteFrame: { x: boxX.toFixed(2), y: boxY.toFixed(2), width: boxWidth.toFixed(2), height: boxHeight.toFixed(2) },
|
|
374
|
-
note: "
|
|
376
|
+
note: "Points in wrapper-relative coords - same as touch events and crop_image_size",
|
|
375
377
|
});
|
|
376
378
|
|
|
377
379
|
setPoints(newPoints);
|
|
@@ -1264,8 +1266,22 @@ const rotatePreviewImage = async (degrees) => {
|
|
|
1264
1266
|
try {
|
|
1265
1267
|
console.log("=== Starting pixel-perfect metadata export (no bitmap crop on mobile) ===");
|
|
1266
1268
|
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
+
let actualImageWidth = originalImageDimensions.current.width;
|
|
1270
|
+
let actualImageHeight = originalImageDimensions.current.height;
|
|
1271
|
+
|
|
1272
|
+
// ✅ CRITICAL: Camera JPEGs often have EXIF 6 (90° CW). The Image component displays
|
|
1273
|
+
// the EXIF-corrected view (3120×4160 portrait) but takePictureAsync returns raw (4160×3120).
|
|
1274
|
+
// Use swapped dimensions for coordinate conversion so bbox matches what the user sees.
|
|
1275
|
+
const isCoverMode = !!(cameraFrameData.current && cameraFrameData.current.greenFrame);
|
|
1276
|
+
const captured = cameraFrameData.current?.capturedImageSize;
|
|
1277
|
+
if (isCoverMode && captured && captured.width > captured.height) {
|
|
1278
|
+
actualImageWidth = captured.height;
|
|
1279
|
+
actualImageHeight = captured.width;
|
|
1280
|
+
console.log("✅ Using EXIF-swapped dimensions for bbox (raw was landscape, display is portrait):", {
|
|
1281
|
+
raw: { w: captured.width, h: captured.height },
|
|
1282
|
+
display: { w: actualImageWidth, h: actualImageHeight },
|
|
1283
|
+
});
|
|
1284
|
+
}
|
|
1269
1285
|
|
|
1270
1286
|
if (actualImageWidth === 0 || actualImageHeight === 0) {
|
|
1271
1287
|
throw new Error("Original image dimensions not available. Please wait for image to load.");
|
|
@@ -1296,7 +1312,6 @@ const rotatePreviewImage = async (degrees) => {
|
|
|
1296
1312
|
}
|
|
1297
1313
|
}
|
|
1298
1314
|
|
|
1299
|
-
const isCoverMode = !!(cameraFrameData.current && cameraFrameData.current.greenFrame);
|
|
1300
1315
|
let scale, coverOffsetX = 0, coverOffsetY = 0;
|
|
1301
1316
|
if (isCoverMode) {
|
|
1302
1317
|
scale = Math.max(displayedWidth / actualImageWidth, displayedHeight / actualImageHeight);
|