sekoyo / react-image-crop

A responsive image cropping tool for React
ISC License
3.77k stars 339 forks source link

Image Cropping with 8/3 Aspect Ratio Causing Loss of Half Portion After Retrieval for s3 #573

Closed alenjoy7 closed 6 months ago

alenjoy7 commented 6 months ago

Problem Summary:

When cropping an image with a size of 5596x3731 using an 8/3 aspect ratio and uploading it to S3, retrieving the image results in the loss of half the image's portion, which is visible in the preview canvas. However, when using a lower size image, this issue does not occur.

Steps to Reproduce:

  1. Upload an image with the size 5596x3731 to the system.
  2. Crop the image using an 8/3 aspect ratio.
  3. Upload the cropped image to S3.
  4. Retrieve the image from S3.
  5. Observe the missing half portion of the image in the preview. 1703851840296-resturant
alenjoy7 commented 6 months ago

preview canvas

import { PixelCrop } from "react-image-crop";
export async function canvasPreview(
  image: HTMLImageElement,
  canvas: HTMLCanvasElement,
  crop: PixelCrop,
  scale = 1,
) {
  const ctx = canvas.getContext("2d");

  if (!ctx) {
    throw new Error("No 2d context");
  }

  const scaleX = image.naturalWidth / image.width;
  const scaleY = image.naturalHeight / image.height;

  const pixelRatio = window.devicePixelRatio;

  canvas.width = Math.floor(crop.width * scaleX * pixelRatio);
  canvas.height = Math.floor(crop.height * scaleY * pixelRatio);

  ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
  ctx.imageSmoothingQuality = "high";

  const cropX = crop.x * scaleX;
  const cropY = crop.y * scaleY;
  const centerX = image.naturalWidth / 2;
  const centerY = image.naturalHeight / 2;
  ctx.fillStyle = "white";
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  ctx.save();

  ctx.translate(-cropX, -cropY);

  ctx.translate(centerX, centerY);
  ctx.scale(scale, scale);
  ctx.translate(-centerX, -centerY);
  const imageObj = new Image();
  imageObj.crossOrigin = "Anonymous";
  imageObj.onload = () => {
    ctx.drawImage(
      imageObj,
      0,
      0,
      image.naturalWidth,
      image.naturalHeight,
      0,
      0,
      image.naturalWidth,
      image.naturalHeight,
    );

    ctx.restore();
  };
  imageObj.src = image.src;
}

code to make it as file

previewCanvasRef?.current?.toBlob(
        (blob) => {
          const file = new File([blob], imageName, {
            type: mimeTypes[fileExtension],
          });

          if (handleCropImageSave) {
            handleCropImageSave(file);
            onclose();
          }
        },
        mimeTypes[fileExtension],
        0.9,
      );
alenjoy7 commented 6 months ago

it was an @fastify/multipart problem because default filesize was 1mb