Dan
Dan

Reputation: 329

Fabric.js canvas image antialiasing

Is there a way to antialiase image that added to canvas using fabric.js I'm having trouble to do this with scaleToHeight function. I couldn't find any suitable option in fabric library.

var canvas = new fabric.Canvas('canvas');
var url = 'https://grafikoan.files.wordpress.com/2012/10/spheres-grafic-design-grafikoan-hd-300-p-2.png';
fabric.Image.fromURL(url, function (oImg) {
	oImg.scaleToHeight(canvas.getHeight());
  canvas.add(oImg);
  canvas.renderAll();
});
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.min.js"></script>
<canvas id="canvas" width=400 height=300></canvas>

As you can see this image looks jagged.

Upvotes: 2

Views: 3741

Answers (2)

AndreaBogazzi
AndreaBogazzi

Reputation: 14731

fabricjs has its own resize filtering to avoid jaggies. Resize filter, with type "sliceHack" is the fastest/good result one. If you do not need dynamic filtering on resize you can also use lanzcos filtering, bilinear, fast hermit.

UPDATE: Since july 2017 with fabric 2.0 there is a sort of lanzcos webgl implementation that is good quality and very fast. By default webgl is on, and there are no alternative alghoritm in the webgl, lanzcos only.

var canvas = new fabric.Canvas('canvas');
var url = 'https://grafikoan.files.wordpress.com/2012/10/spheres-grafic-design-grafikoan-hd-300-p-2.png';
fabric.Image.fromURL(url, function (oImg) {
    var scaling = canvas.getHeight() / oImg.height;
    oImg.filters.push(new fabric.Image.filters.Resize({
        resizeType: 'sliceHack', scaleX: scaling , scaleY: scaling 
    }));
  canvas.add(oImg);
  oImg.applyFilters(canvas.renderAll.bind(canvas));  
},{ crossOrigin: 'Anonymous' });
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<script src="http://www.deltalink.it/andreab/fabric/fabric.js"></script>
<canvas id="canvas" width=400 height=300></canvas>

Please check this link for a working example with no CoR issue.

http://www.deltalink.it/andreab/fabric/resize.html

Compare normale image and sliceHack image, the filter will kick in once you resize.

Here more examples: https://github.com/kangax/fabric.js/issues/1741

Upvotes: 4

markE
markE

Reputation: 105035

The original image is 10X the size of the desired size.

Scaling downward by 10X is causing your "jaggies". Yes, scaling downward can cause jaggies just like scaling upward can cause jaggies.

You can lessen the jaggies by incrementally scaling the original image downward towards the desired size.

Here is example code and a Demo:

The original image is downscaled 4 times by half and then scaleToHeight is applied to get the final size of the fabric.Image.

enter image description here

var canvas = new fabric.Canvas('canvas');

var downscaledImg;
var img=new Image();
img.onload=start;
img.src="https://grafikoan.files.wordpress.com/2012/10/spheres-grafic-design-grafikoan-hd-300-p-2.png";
function start(){
    // create a canvas that is 4x smaller than the original img
    downscaledImg=downscale(img,4);
    // create a fabric.Image from the downscaled image
    var fImg=new fabric.Image(downscaledImg);
    fImg.scaleToHeight(canvas.getHeight());
    canvas.add(fImg);
    canvas.renderAll();
}

function downscale(img,halfCount){
    var cc;
    var c=document.createElement('canvas');
    c.width=img.width/2;
    c.height=img.height/2;
    c.getContext('2d').drawImage(img,0,0,img.width/2,img.height/2);
    halfCount--;
    for(var i=0;i<halfCount;i++){
        cc=document.createElement('canvas');
        cc.width=c.width/2;
        cc.height=c.height/2;
        cc.getContext('2d').drawImage(c,0,0,c.width/2,c.height/2);
        halfCount--;
        c=cc;
    }
    return(c);
}
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.min.js"></script>
<canvas id="canvas" width=400 height=300></canvas>    </body>

Upvotes: 4

Related Questions