Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid seams between filled areas in canvas?

When I fill adjacent areas in HTML5 Canvas or similar systems like Quartz or GDI+, I see a light colored seam on the shared edge. Here's an example, (code below):

enter image description here

I think I understand what's going on but don't have a fix. Each edge is anti-aliased against white, so instead of a mix of orange and blue you get a mix of orange, blue and white.

Essentially the same question has been asked before but with less discussion and no good answer.

Some work-arounds that involve drawing the first shape a little bigger at the seam or drawing a line over the seam do not hold up over variations like with transparency or odd shape combinations.

Turning off anti-aliasing avoids the seam for APIs that support it, but then, of course, all the edges are jagged.

Is there a way to provide a hint to the renderer about the intended adjacency?

<canvas id="myCanvas" width="300" height="150" /> <script>
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.moveTo(100,0);  ctx.lineTo(115,150);  ctx.lineTo(300, 50);
ctx.closePath();  ctx.fillStyle="#885533";  ctx.fill();

ctx.beginPath();
ctx.moveTo(0,50);  ctx.lineTo(100,0);  ctx.lineTo(115,150);
ctx.closePath();  ctx.fillStyle="#335588";  ctx.fill();
</script>  </body>  </html>
like image 796
xan Avatar asked Oct 11 '13 13:10

xan


1 Answers

If you’re drawing on a transparent canvas and your shapes are nonoverlapping, you can simply set ctx.globalCompositeOperation = "lighter":

your example with globalCompositeOperation = "lighter"

That means each shape will combine its contribution with the previous contents of its pixels using simple addition instead of typical alpha blending. That’s exactly what you want in this case.

like image 108
Anders Kaseorg Avatar answered Oct 14 '22 21:10

Anders Kaseorg