简体   繁体   English

如何裁剪超出图像边界的图像,就像我想通过添加透明/白色边距从 4:3 图像制作 1:1 图像一样?

[英]How can I crop an image beyond image boundary like I want to make a 1:1 image from a 4:3 image by adding transparent/white margins to it?

Currently, I am using 'react-image-crop' package to crop my images.目前,我正在使用 'react-image-crop' package 来裁剪我的图像。 But the issue I am facing right now is that I need a 1:1 company logo to be uploaded by the client but if the shape of the image is not a square then the user will not be able to upload the whole logo and image cropping library will crop it to 1:1 and remove/strip some part of it.但我现在面临的问题是我需要一个 1:1 的公司标志由客户上传,但如果图像的形状不是正方形,那么用户将无法上传整个标志和图像裁剪库会将其裁剪为 1:1 并删除/剥离其中的一部分。 Whereas I want to make it like WhatsApp profile photo upload where it allows you to crop/reshape an image beyond its boundaries in order to make it 1:1 and add some blur.而我想让它像 WhatsApp 个人资料照片上传一样,它允许您裁剪/重塑图像超出其边界,以使其 1:1 并添加一些模糊。 I just want to add white/transparent background to newly added space.我只想为新添加的空间添加白色/透明背景。 Please let me know if there is a way to achieve this using 'react-image-crop' or any other package.请让我知道是否有办法使用“react-image-crop”或任何其他 package 来实现这一点。

Side Note: Actually I need a 5:2 image instead of 1:1.旁注:实际上我需要一个 5:2 的图像而不是 1:1。 1:1 is easy to imagine/visualise that's why I took that example. 1:1 很容易想象/可视化,这就是我举这个例子的原因。

this is what my component looks like:这就是我的组件的样子:

    export default function ImageCrop (props){
        const [img, setUpImg] = useState()
        const imgRef = useRef(null)
        const [crop, setCrop] = useState({ unit: 'px', width: 200, aspect: 5 / 2 })
        const [previewUrl, setPreviewUrl] = useState()
        
    
        useEffect(() => {
            
            onSelectFile(props.file)
        }
        ,[props.file])
        const onSelectFile = file => {
          
            const reader = new FileReader();
            reader.addEventListener('load', () => setUpImg(reader.result));
            reader.readAsDataURL(file);
          }
        
      
        const onLoad = useCallback(img => {
          imgRef.current = img;
        }, []);
      
        const makeClientCrop = async crop => {
          if (imgRef.current && crop.width && crop.height) {
            const cropped = await getCroppedImg(imgRef.current, crop, props.file.name);
            window.URL.revokeObjectURL(previewUrl);
              setPreviewUrl(window.URL.createObjectURL(cropped));
              props.updateBuffer(cropped)
             

 console.log(cropped)
        
      }
    };
  
    function getCroppedImg(image, crop, fileName) {
        const canvas = document.createElement('canvas');
        const scaleX = image.naturalWidth / image.width;
        const scaleY = image.naturalHeight / image.height;
        canvas.width = crop.width;
        canvas.height = crop.height;
        const ctx = canvas.getContext('2d');
       
        ctx.drawImage(
          image,
          crop.x * scaleX,
          crop.y * scaleY,
          crop.width * scaleX,
          crop.height * scaleY,
          0,
          0,
          crop.width,
          crop.height,
        );
       
        // As Base64 string
        // const base64Image = canvas.toDataURL('image/jpeg');
       
        // As a blob
        return new Promise((resolve, reject) => {
          canvas.toBlob(blob => {
            blob.name = fileName;
            resolve(blob);
          }, 'image/jpeg', 1);
        });
      }
   
    return (
      <div className="App">
        
        <ReactCrop
          src={img}
          onImageLoaded={onLoad}
          crop={crop}
          onChange={c => setCrop(c)}
          onComplete={makeClientCrop}
          style={{width: '50%'}}
        />
        {previewUrl && <img alt="Crop preview" src={previewUrl} />}
      </div>
    )
    }
    

At the moment you initialise the canvas dimensions in the getCroppedImg() method you could take the longest side of the loaded image and create a square canvas based on that value, then just centre the image horizontally or vertically accordingly在 getCroppedImg() 方法中初始化 canvas 尺寸时,您可以取加载图像的最长边并根据该值创建一个正方形 canvas,然后相应地水平或垂直居中图像

在此处输入图像描述

May be add extra pixels to W as a way of a margin to give you more room, and centre as suggested by Andreas in the comments可能会向 W 添加额外的像素作为边距的一种方式,以便为您提供更多空间,并按照 Andreas 在评论中的建议居中

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM