prisel
prisel

Reputation: 337

how to remove jagged lines in canvas?

In my project I am showing image preview using canvas design. My original image is Original image

Using canvas I curved top and bottom like this Curved image.

enter image description here

But its top and bottom is jagged.

<!DOCTYPE HTML>
 <html>
  <head>
   <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
  </head>
  <body>
   <section id="test"></section>
   <script>
    var image = new Image();
    image.id = "imgBendSource";
    image.style.display = "none";
    image.onload = function() {
    $("#test").append(image);
    var newWidth = "415";
    var newHeight = "285";
    var img = document.getElementById("imgBendSource");
    var x1 = 415 / 2;
    var x2 = 415;
    var y1 = 15; // input y of O here
    var y2 = 0;
    var eb = (y2 * x1 * x1 - y1 * x2 * x2) / (x2 * x1 * x1 - x1 * x2 * x2);
        var ea = (y1 - eb * x1) / (x1 * x1);
        var canvasHeight = parseInt(newHeight) + y1;
        // create a new canvas for bend image
        var canvasElement = '<canvas id="imgBendCanvas" width="' + newWidth + '" height="' + canvasHeight + '"/>';

        $("#test").append(canvasElement);
        canvasElement = document.getElementById("imgBendCanvas");
        var bendCtx = canvasElement.getContext('2d');

        for (var x = 0; x < newWidth; x++) {
            // calculate the current offset
            currentYOffset = (ea * x * x) + eb * x;

            bendCtx.drawImage(img, x, 0, 1, newHeight, x, currentYOffset, 1, newHeight);
        }
    }
    image.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
</script>
</body>
</html>

Is there any other way to achieve it? any plugins available?

Upvotes: 1

Views: 935

Answers (2)

bjanes
bjanes

Reputation: 263

The image is clearly cut at integer values which could be bcos the specific browser in use. you can try to draw the bent image in double resolution and draw it back at half the size. i can't get the jaggis whatever i do but i can't test with safari. you should test in other browsers to see it this is the case.

--update--

I added modified code below (code based on markE's example). the main changes is that you use two scaling factors: one for internal scaling to compensate for the integer aliasing, and then the destination scale. by scaling down this way the browser should smooth the image. try higher scaling values if need be. if too high diff you will probably need scale down in more steps than one. i found this answer and this answer that helps with that issue.

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");

var img=new Image();
img.onload=start;
img.src='https://i.sstatic.net/OgllG.png';
function start(){
    //----changes here
    var scalingFactor=2.0; // the internal scaling
    var scalingFactorDst=0.5; // target scaling
    var curved=curveImage(img,15,2,scalingFactor);
    ctx.drawImage(curved,5,5,curved.width*scalingFactorDst,curved.height*scalingFactorDst);    
    //----end of changes
}

function curveImage(img,curveDepthY,blurFactor,scalingFactor){
    var c=document.createElement('canvas');
    var ctx=c.getContext('2d');
    c.width=img.width;
    c.height=(img.height+curveDepthY+blurFactor);
    //
    var newWidth = img.width;
    var newHeight = img.height;
    var x1 = img.width/2;
    var x2 = img.width;
    var y1 = curveDepthY; // input y of O here
    var y2 = 0;
    var eb = (y2 * x1 * x1 - y1 * x2 * x2) / (x2 * x1 * x1 - x1 * x2 * x2);
    var ea = (y1 - eb * x1) / (x1 * x1);
    for (var x = 0; x < newWidth; x++) {
        // calculate the current offset
        currentYOffset = (ea * x * x) + eb * x;
        ctx.drawImage(img, x, 0, 1, newHeight, x, currentYOffset, 1, newHeight);
    }
    // create a resized version of the curved image
    //     with a shadow to help smooth the jaggies
    var cc=document.createElement('canvas');
    var cctx=cc.getContext('2d');
    cc.width=img.width*scalingFactor;
    cc.height=(img.height+curveDepthY+blurFactor)*scalingFactor;
    cctx.scale(scalingFactor,scalingFactor);
    cctx.shadowColor='gray';
    cctx.shadowBlur=blurFactor;
    cctx.drawImage(c,0,0);
    return cc;
}
<canvas id="canvas" width=512 height=512></canvas>

Upvotes: 0

AgataB
AgataB

Reputation: 647

It depends what you mean by "clear". If you're looking for transparency, then canvas are transparent by default, and you can indeed see the background behind the curved image around the curved bits. To better see that, set the background color of the body.

So how did you arrive at the conclusion that it is not transparent? Are you exporting the image to a format that supports transparency, like .gif or .png? Note: .jpg does not support it.

EDIT: the clarification in the question makes this answer no longer relevant. Please refer to the other answer.

Upvotes: 1

Related Questions