Pixel art in HTML5 canvas is blurry when scaled up
Asked Answered
D

1

19

I am trying to make a pixel art themed game in HTML5 canvas, and as part of that I take 10x20 or so sized images and draw them onto the canvas with the following code:

ctx.drawImage(image, 20, 20, 100, 200);

However the canvas uses bicubic image scaling and hence the pixel art images look terrible at 2× and up. Is there a way to force canvas to use nearest neighbor scaling or possibly use a custom method to scale images? If not, does that mean the images have to be scaled beforehand in something like Paint.net?

Deidradeidre answered 9/5, 2012 at 22:37 Comment(0)
O
43

Choose any one of the following:


Via JavaScript:

ctx.imageSmoothingEnabled = false;

Source: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#image-smoothing

On Gecko, you'll need

ctx.mozImageSmoothingEnabled = false;

Source: https://developer.mozilla.org/en/DOM/CanvasRenderingContext2D#Gecko-specific_attributes

On Webkit, you'll need

ctx.webkitImageSmoothingEnabled = false;

Source: https://bugs.webkit.org/show_bug.cgi?id=82804

I couldn't find information on support of this property on other browsers, so they probably don't support it.


Via CSS:

Another option is to use a set of CSS rules on the canvas. For example:

<canvas id="c" width="16" height="16"></canvas>
<script>
  var c = document.getElementById("c"),
      cx = c.getContext("2d"),
      im = new Image();
  im.src = "http://stackoverflow.com/favicon.ico"; // 16x16
  cx.drawImage(im, 0, 0);
</script>
<style>
  canvas {
    width: 32px;
    height: 32px;
    image-rendering: optimizeSpeed;
    image-rendering: crisp-edges;
    image-rendering: -moz-crisp-edges;
    image-rendering: -o-crisp-edges;
    image-rendering: -webkit-optimize-contrast;
    -ms-interpolation-mode: nearest-neighbor;
  }
</style>

Source: https://developer.mozilla.org/en/CSS/image-rendering
Source: https://bugs.webkit.org/show_bug.cgi?id=56627


Via pixel routines:

Yet another option is to do it yourself using the canvas pixel manipulation routines: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#pixel-manipulation. That's a lot more work, though.

On answered 9/5, 2012 at 22:42 Comment(7)
What a complete answer!Salley
Was that intentional to use width & height as 200 in the CSS definition, whilst the original size of the canvas being 100*100?Ivey
@SatyaKalluri: Yes. If you set width,height:200px in CSS and width,height="100" in HTML, each "pixel" in the canvas shows up as 2×2 pixels on the screen.On
You're missing something in your css: image-rendering: -moz-crisp-edges That's how you do this on firefox.Wilbourn
@tieTYT: Thanks! The behavior of Firefox must have changed since I posted this. Updated.On
this works in 2024Protege
this solution doesn't work for me in chromium (and chrome and edge), where image-rendering: pixelated; does work instead.Lent

© 2022 - 2024 — McMap. All rights reserved.