Fabric.js 中的像素化图像,使用 sliceHack Resize 滤镜

Pixelated image in Fabric.js with sliceHack Resize filter

有时我无法找到使用调整大小过滤器 (slideHack) 而不获取像素化图像的方法。 我使用 fabric.js 1.7.2

  1. 我刚刚在canvas

    中添加了图片
    fabric.Image.fromURL(url, function(oImg) 
    {
        var scaling = 0.2;
        var rFilter = new fabric.Image.filters.Resize({
            resizeType: 'sliceHack'
        });
        oImg.resizeFilters.push(rFilter);
        oImg.applyFilters();
    
        oImg.set({
            left:   300, 
            top:    300, 
            scaleX: scaling, 
            scaleY: scaling
        });
    
        canvas.add(oImg);
        canvas.renderAll();
    });
    
  2. 当我点击图片或手动调整图片大小时,边缘变得平滑。

  3. 当我应用色调滤镜时,它又被像素化了

我找不到触发平滑边缘的函数...

感谢您的帮助。

文档 Introduction to Fabric.js, Part 2 建议使用以下语法,这似乎可以解决问题:

fabric.Image.fromURL('pug.jpg', function(img) {

  // add filter
  img.filters.push(filter);

  // apply filters and re-render canvas when done
  img.applyFilters(canvas.renderAll.bind(canvas));

  // add image onto canvas
  canvas.add(img);
});

将结果与下面代码段中的原始方法进行比较。为了让它工作,我还添加了 { crossOrigin: 'Anonymous' }(请参阅 AndreaBogazzi 对 的评论)。

var canvas = new fabric.Canvas('c');
var ctx = canvas.getContext("2d");
var url = 'http://i.imgur.com/a47Yxsb.png';
var imgWidth = 770;

function performScaling() {
  // Get scaling factor
  var scaling =  parseFloat(document.getElementById("txtScaling").value);

  canvas.clear();

  // With original method
  fabric.Image.fromURL(url, function(oImg) 
  {
    var rFilter = new fabric.Image.filters.Resize({
      resizeType: 'sliceHack'
    });
    oImg.resizeFilters.push(rFilter);
    oImg.applyFilters();

    oImg.set({
      left:   0, 
      top:    16, 
      scaleX: scaling, 
      scaleY: scaling
    });

    canvas.add(oImg);
    canvas.renderAll();
  });

  // As suggested in Fabric.js introduction
  fabric.Image.fromURL(url, function (oImg) {
      oImg.filters.push(new fabric.Image.filters.Resize({
          resizeType: 'sliceHack', scaleX: scaling , scaleY: scaling 
      }));
    oImg.set({
      left: imgWidth * 1.1 * scaling,
      top: 16
    });
    oImg.applyFilters(canvas.renderAll.bind(canvas));  
    canvas.add(oImg);
  },{ crossOrigin: 'Anonymous' });
  
  // Add labels
  canvas.add(new fabric.Text('Pixelated', {
    fontFamily: 'Arial',
    fontSize: 12,
    left: 0.48 * imgWidth * scaling,
    top: 0,
    fill: 'black',
    originX: 'center'
  }));  
  
  canvas.add(new fabric.Text('Not pixelated', {
    fontFamily: "Arial",
    fontSize: 12,
    left: 1.58 * imgWidth * scaling,
    top: 0,
    fill: 'black',
    originX: 'center'
  }));  
}
#divScaling
{
  display: inline-block;
  vertical-align: middle;
  margin: 6px 32px 16px 0px;
  vertical-align: top;
}

#txtScaling
{
  width: 70px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.2/fabric.min.js"></script>
<div id="divScaling">
  <label for="txtScaling">Scaling factor: </label>
  <input id="txtScaling" type="text" value="0.2" />
  <button onclick="performScaling()">
  Scale
  </button>
</div>
<img src="http://i.imgur.com/a47Yxsb.png" style="width: 30px;height: 30px;"/>

<canvas id="c" width="600" height="400"></canvas>

我认为像素化问题已在版本 2 中得到修复。边缘比版本 1.72 更平滑

注意 v2 中的重大更改:

Another breaking change is that the .resizeFilters is no more an array of resize filter. Is a single resizeFilter that you can use when the object is scaled on the canvas.

image.resizeFilter = new fabric.Image.filters.ResizeFilter({type: 'hermite'});

var canvas = new fabric.Canvas('c');
var ctx = canvas.getContext("2d");
var url = 'http://i.imgur.com/a47Yxsb.png';
var imgWidth = 1024;

function performScaling() {
  // Get scaling factor
  var scaling =  parseFloat(document.getElementById("txtScaling").value);

  canvas.clear();

  // As suggested in Fabric.js introduction
  fabric.Image.fromURL(url, function (oImg) {
    oImg.set({
      left: imgWidth * 1.1 * scaling,
      top: 16
    });
    oImg.scale(scaling);
    oImg.resizeFilter = new fabric.Image.filters.Resize({
        resizeType: 'sliceHack'
    });
    oImg.applyResizeFilters();
    canvas.add(oImg);
    canvas.renderAll();

    // canvas.setBackgroundImage(
    //   oImg,
    //   () => {
    //     canvas.renderAll();
    //   },
    // );
    
  },{ crossOrigin: 'Anonymous' });
  
  // Add labels
  
  canvas.add(new fabric.Text('Not pixelated', {
    fontFamily: "Arial",
    fontSize: 12,
    left: 1.58 * imgWidth * scaling,
    top: 0,
    fill: 'black',
    originX: 'center'
  }));  
}
#divScaling
{
  display: inline-block;
  vertical-align: middle;
  margin: 6px 32px 16px 0px;
  vertical-align: top;
}

#txtScaling
{
  width: 70px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.4/fabric.min.js"></script>
<div id="divScaling">
  <label for="txtScaling">Scaling factor: </label>
  <input id="txtScaling" type="text" value="0.2" />
  <button onclick="performScaling()">
  Scale
  </button>
</div>
<img src="http://i.imgur.com/a47Yxsb.png" style="width: 30px;height: 30px;"/>

<canvas id="c" width="600" height="400"></canvas>