diff --git a/app/components/store/ImageEditor.tsx b/app/components/store/ImageEditor.tsx index a27be80..66e3212 100644 --- a/app/components/store/ImageEditor.tsx +++ b/app/components/store/ImageEditor.tsx @@ -302,20 +302,30 @@ export function ImageEditor({ const adjustedCropWidth = cropArea.width * scaleX; const adjustedCropHeight = cropArea.height * scaleY; - // Set canvas size to crop area - canvas.width = cropArea.width; - canvas.height = cropArea.height; + // Crop rectangle expressed in the SOURCE image's native pixels + // (adjusted* already scales the on-screen crop back up to the original). + const srcX = Math.max(0, adjustedCropX); + const srcY = Math.max(0, adjustedCropY); + const srcWidth = Math.min(adjustedCropWidth, img.width - srcX); + const srcHeight = Math.min(adjustedCropHeight, img.height - srcY); + + // Size the canvas to the full-resolution crop region, NOT the editor's + // on-screen crop size. Using the display size here was downscaling phone + // photos to a few hundred pixels, which is what made uploads blurry. + // The backend still caps the final image to 1600px. + canvas.width = Math.max(1, Math.round(srcWidth)); + canvas.height = Math.max(1, Math.round(srcHeight)); // Clear canvas ctx.clearRect(0, 0, canvas.width, canvas.height); - // Draw the cropped portion + // Draw the cropped portion at native resolution ctx.drawImage( img, - Math.max(0, adjustedCropX), - Math.max(0, adjustedCropY), - Math.min(adjustedCropWidth, img.width - Math.max(0, adjustedCropX)), - Math.min(adjustedCropHeight, img.height - Math.max(0, adjustedCropY)), + srcX, + srcY, + srcWidth, + srcHeight, 0, 0, canvas.width, @@ -331,7 +341,7 @@ export function ImageEditor({ onClose(); }, "image/jpeg", - 0.9 + 0.92 ); };