【问题标题】:Applying filters to large images using FabricJS使用 FabricJS 对大图像应用过滤器
【发布时间】:2020-10-16 09:51:40
【问题描述】:

我正在尝试对 FabricJS 中的大图像应用过滤器。

图像大约为 3000 x 4000,超过了默认的 2048 纹理大小。我可以将它增加到 4096,它适用于这张图片。

当前,当应用过滤器时,图像会被剪切。我尝试使用以下方法减小图像的大小:

let obj = this.canvas.getActiveObject();
if (Math.max(obj.width, obj.height) > 2048) {
  let scale = 2048 / Math.max(obj.width, obj.height);
  obj.filters.push(
    new fabric.Image.filters.Resize({ scaleX: scale, scaleY: scale })
  );
}
obj.filters.push(new fabric.Image.filters.Grayscale());
obj.applyFilters();
this.canvas.renderAll();

但这对我不起作用。图像仍被剪切和旋转。

这就是我将图像添加到画布的方式:

//in a parent component
let url = URL.createObjectURL(e.target.files[0]);
fabric.Image.fromURL(url, (image) => {
  this.setState({
    image,
  });
});

//following is in a child component
let canvasWidth = this.canvasWrapperRef.current.clientWidth;
let canvasHeight = this.canvasWrapperRef.current.clientHeight;
//create canvas
this.canvas = new fabric.Canvas("canvas", {
  selection: false,
  backgroundColor: "black",
  hoverCursor: "context-menu",
  height: canvasHeight,
  width: canvasWidth,
});
let image = this.props.image;
image.set({ selectable: false });
this.canvas.centerObject(image);
this.canvas.setActiveObject(image);
this.canvas.add(image);
this.canvas.renderAll();

有没有办法可以减小原始图像的大小/质量,以便对其应用过滤器?

【问题讨论】:

    标签: image canvas fabricjs


    【解决方案1】:

    我花了几天的时间,但我终于找到了解决我遇到的问题的方法。似乎当您使用织物调整图像大小时,它会保留原始大小。为了解决这个问题,我将图像添加到可以处理过滤器的大小的画布中,然后将该画布导出为图像并以通常的方式将其添加到织物中。

    对我来说,这似乎是一个 hacky 解决方案,但它确实有效,但如果有人知道更好的解决方案,请告诉我。

    //handle the image uploading process
    handleImageUpload = async (e) => {
      if (e.target.files.length < 1) return;
      let objectUrl = URL.createObjectURL(e.target.files[0]);
      //resize if needed
      let imageUrl = await this.resizeImage(this.textureSize, objectUrl);
      fabric.Image.fromURL(imageUrl, (image) => {
        this.setState({
          image,
        });
      });
    };
    
    //resize the image if one of the sides of the image exceeds the max texture size
    //if the image requires resizing, create a canvas element but don't attach to DOM
    //size the canvas with the largest size being equal to the max texture size
    //then scale the image down to the correct size when adding to the canvas
    resizeImage = (maxSize, imageUrl) => {
      return new Promise((resolve) => {
        let image = new Image();
        image.src = imageUrl;
        image.onload = (img) => {
          //check if resizing is required
          if (Math.max(img.target.width, img.target.height) > maxSize) {
            //create canvas
            let canvas = document.createElement("canvas");
            //scale image
            if (img.target.height >= img.target.width) {
              canvas.height = maxSize;
              canvas.width = (maxSize / img.target.height) * img.target.width;
            } else {
              canvas.width = maxSize;
              canvas.height = (maxSize / img.target.width) * img.target.height;
            }
            //draw to canvas
            let context = canvas.getContext("2d");
            context.drawImage(img.target, 0, 0, canvas.width, canvas.height);
            //assign new image url
            resolve(context.canvas.toDataURL());
          }
          resolve(imageUrl);
        };
      });
    };
    

    我使用 2048 作为我的最大纹理大小。高于此的任何内容和过滤器都会开始剪切和旋转图像。我认为这是由硬件决定的,我使用2048作为一个相对安全的限制。请参阅此处了解更多信息:http://fabricjs.com/fabric-filters

    当您使用上述方法缩小图像时,您的图像质量可能会下降。更好的解决方案可能是使用内置的织物缩小图像的方法(我没有测试过这个,但我想织物会比上述方法更好地处理重新缩放),然后类似于上面的导出和重新导入。然而,由于这只是一个旨在学习 react 的个人项目,我很高兴接受图像质量的影响并显示警告,即大图像尺寸会被调整大小并且可能会降低质量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-31
      • 2017-05-10
      • 2019-05-22
      • 2013-05-02
      • 2018-12-17
      • 2013-11-02
      • 2015-06-17
      • 1970-01-01
      相关资源
      最近更新 更多