Higher pixels image are not cropping properly in react js when using react image crop package

283 Views Asked by At

I am playing around cropping and zooming the image and it is almost done as per my requirement but using images higher than 700 pixels, the crop image is not cropping properly.

I tried to change the processing but no help.

I am trying to upload images that are more than 5 MB in size and higher pixels around more than 1000 * 1000 px. but when I upload the image the crop is not working properly.

When I resize the image around 670*700 px then cropping is working fine.

I need help or guidance on this.

{manipulatedImage && (
<ReactCrop
                  className="reactcrop-style"
                  crop={crop}
                  onChange={(newCrop) => setCrop(newCrop)}
                  onComplete={onCropComplete}
                  minHeight={200}
                >
                  <div className="image-fiter-style">
                    <div style={{ width: "100%" }}>
                      <ImageFilter
                        image={manipulatedImage}
                        filter={filter !== "none" ? filter : undefined}
                        colorOne={[40, 250, 250]}
                        colorTwo={[250, 150, 30]}
                        style={{
                          width: "100%",
                          height: "auto",
                          transform: `scale(${imageZoomLevel / 100})`,
                          transformOrigin: "top left",
                        }}
                      />
                    </div>
                  </div>
                </ReactCrop>
              )}
const getCroppedImg = (imageSrc, crop) => {
    const image = new Image();
    image.src = imageSrc;

    return new Promise((resolve) => {
      image.onload = () => {
        const canvas = document.createElement("canvas");
        const zoomFactor = imageZoomLevel / 100; // Calculate zoom factor
        const pixelRatio = window.devicePixelRatio;
        
        const ctx = canvas.getContext("2d");
        canvas.width = crop.width * pixelRatio; // Adjust canvas size for zoom
        canvas.height = crop.height * pixelRatio;
        ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
      ctx.imageSmoothingQuality = 'high';

        ctx.drawImage(
          image,
          crop.x * zoomFactor, // Adjust crop position for zoom
          crop.y * zoomFactor,
          crop.width * zoomFactor,
          crop.height * zoomFactor,
          0,
          0,
          crop.width ,
          crop.height 
        );

        canvas.toBlob((blob) => {
          const croppedImageUrl = URL.createObjectURL(blob);
          resolve(croppedImageUrl);
        }, "image/jpeg");
      };
    });
  };

This is my react crop code.

1

There are 1 best solutions below

0
Natália On

When creating the canvas for cropping, you are adjusting the canvas size for zoom, but you also set the canvas width and height to crop.width and crop.height. This may cause issues when cropping high-resolution images. While working with similar usecases, I have felt that setting a fixed size for the canvas and adjusting the crop coordinates accordingly is better. Something like this can help ensure that the cropping works consistently for both small and large images:

const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");

// Set a fixed canvas size for cropping
canvas.width = crop.width;
canvas.height = crop.height;

// Adjust crop coordinates for zoom
const zoomFactor = imageZoomLevel / 100;
const scaledCrop = {
  x: crop.x * zoomFactor,
  y: crop.y * zoomFactor,
  width: crop.width * zoomFactor,
  height: crop.height * zoomFactor,
};

ctx.drawImage(
  image,
  scaledCrop.x,
  scaledCrop.y,
  scaledCrop.width,
  scaledCrop.height,
  0,
  0,
  crop.width,
  crop.height
);

Also, should do more error handling in longer code. For eg:

return new Promise((resolve, reject) => {
  image.onload = () => {
    // You code

    image.onerror = (error) => {
      reject(error);
    };
  };

  image.onerror = (error) => {
    reject(error);
  };
});

One last suggestion would be to consider server side cropping.For very large images, it's often more efficient to perform cropping and resizing on the server side. You can upload the image to your server, process it there using server-side libraries or services (like Cloudinary or ImageMagick), and then send the processed image back to the client. Here's a basic example of how to crop and resize an image this way:

// Example URL to crop and resize an image using Cloudinary
const imageUrl = cloudinary.url('your-image', {
  width: 500,     
  height: 700, 
  crop: 'fill',    // Crop mode 
  gravity: 'auto', // Crop positioning
});

Hope this solves your issue.