react-crop-image error in converting canvas to blob

1.3k Views Asked by At

I would like to create a module in my site about cropping the image of an article. I am using the react-crop-image.

I am having a problem on converting my canvas to blob. I am getting an error of SecurityError: Failed to execute 'toBlob' on 'HTMLCanvasElement': Tainted canvases may not be exported. I would like to find another solution or way to crop an image if there would be suggestion.

Here is what I'm following:

I have this code in react to crop the image and draw it in canvas.

<ReactCrop
src={state.featureImagePreview}
onImageLoaded={onLoad}
crop={cropImage}
onChange={
  (c) => setImageCrop(c)
}
onComplete={(c) => setCompletedCrop(c)}
/>
<div>                                    
<canvas
  ref={previewCanvasRef}
  style={{
    width: Math.round(completedCrop?.width ?? 0),
    height: Math.round(completedCrop?.height ?? 0)
    // display: "none"
  }}
/>                                    
</div>

Now, I would like to convert this to blob and to POST in api server, I created a button to submit the article and has an event of this function and there where my error occurs:

 const handleSave = (params) => {        
    previewCanvasRef.current.toBlob(
      (blob) => {
        const previewUrl = window.URL.createObjectURL(blob);    
      },
      {useCORS: true},
       'image/wbmp');
}

I was searching about the error and it relates about the CORS. Is there anyway I can crop my image without drawing it with canvas? or any method to crop the image or any solution ?

I was really don't have any idea about the error. so any suggestions just to achieve my goal in cropping the image is very well appreciated.

3

There are 3 best solutions below

1
On BEST ANSWER

I have already solved the problem. I just put anonymous from the react crop tag.

Here is the solution code :

<ReactCrop
src={state.featureImagePreview}
onImageLoaded={onLoad}
crop={cropImage}
onChange={                                        
(c) => setImageCrop(c)
}                                      
onComplete={(c) => setCompletedCrop(c)}
crossorigin='anonymous'                                                                            
/>
0
On

In my case, the problem was ReactCrop was not loading old S3 images properly and more importantly when I was cropping the part, it was returning an empty canvas. Here is my fix:

...
setImageUrl(`${url}?cache=${new Date().getTime()}`); // before fetching image from S3 
...

<ReactCrop
    src={imageUrl} 
    onImageLoaded={onLoad}
    crop={cropImage}
    onChange={                                        
        (c) => setImageCrop(c)
    }                                      
    onComplete={(c) => setCompletedCrop(c)}
    crossorigin='anonymous' // resolve cors                                                                          
/>
0
On

If you are using a remote url directly, then instead of using it directly , convert it into string and then use it.In my case, as soon as I land on the view , I use the code as

useEffect(() => { 

      if(imageURL){
      fetch(imageURL)
      .then(response => response.blob())
      .then(blob => {
        // Convert the image data to a Base64 string.
        console.log('convertedImage', blob)
        const reader = new FileReader();
        reader.onload = () => {
          const result = reader.result;
          if (typeof result === 'string') {
            //const base64String = result.split(',')[1]; // Extract the Base64 data from the result
            console.log(result); // This is your Base64-encoded image string.
            setImgSrc(result)
          } 
        };
        reader.readAsDataURL(blob);
      })
      .catch(error => {
        console.error('Error fetching the image:', error);
      });
      }

  },[imageURL])