Question

Update

It's definitely to do with how I'm rescaling the canvas. If I draw the same scene onto a canvas and I don't change it's width and height to fill the screen, it works perfectly.

Working

What is the correct way to resize a canvas for fullscreen environments?


I'm writing a game engine for canvas and am having problems with images being upscaled and aliased, I read through a couple of answers for people having similar problems. I amended my code to enable the following settings on each of my canvases.

context.webkitImageSmoothingEnabled = false;                                                                                
context.mozImageSmoothingEnabled = false;                                                                                   
context.imageSmoothingEnabled = false;

Just to make sure, I also included the CSS alternatives of these rules.

canvas {
  image-rendering: optimizeSpeed;             // Older versions of FF
  image-rendering: -moz-crisp-edges;          // FF 6.0+
  image-rendering: -webkit-optimize-contrast; // Webkit (non standard naming)
  image-rendering: -o-crisp-edges;            // OS X & Windows Opera (12.02+)
  image-rendering: crisp-edges;               // Possible future browsers.
  -ms-interpolation-mode: nearest-neighbor;   // IE (non standard naming)
}

Here's an example of one of the original images I am trying to draw.

Character

I'm then upscaling from 16x16 to 64x64 and instead of coming out looking like nearest-neighbour interpolation was used, it renders like this.

Actual result

I get the same results in Chrome and Firefox. I don't want to do a preprocessing step to upscale the images, either. It's got to be possible, because this demo works for me.

The other thing to mention, is that the engine is designed to be used in fullscreen, so I am manually keeping the size of the canvases up to date with this function.

fill-screen = (canvas) ->
  canvas.width = document.body.clientWidth
  canvas.height = document.body.clientHeight

The canvases are absolutely positioned to the top left hand corner of their parent, other than that, there are no non-browser CSS rules operating on them.

Maybe I'm doing something stupid, but I've been looking at this for ages and I'm getting no closer. The code for the file where I am creating the canvases and contexts is here: https://gist.github.com/code-curve/9273248

Was it helpful?

Solution

If you resize the canvas the smoothing setting is reset as well (may depend on browser).

After you resize the canvas simply re-apply the imageSmoothingEnabled.

fill-screen = (canvas) ->
  canvas.width = document.body.clientWidth
  canvas.height = document.body.clientHeight
  // re-apply here on context

I would also recommend using window.innerWidth and window.innerHeight instead for the sizes.

My (free) retro context library may also be of interest.

OTHER TIPS

If you don't find an "actual" solution, you can always just scale up the graphics yourself:

var ctxData = ctx.getImageData()
  ,  pixels = ctxData.data
  ,   width = 16
  ,  height = 16
  ,    mult = 4
  ;

for( var x=width*mult-1; x>=0; x-- ){
    for( var y=height*mult-1; y>=0; y-- ){

        // or something close to this
        pixels[ y*width*mult*4 + x ] = pixels[ y*width*4 + x ];
    }
}

// pseudo code
canvas.width  *= mult;
canvas.height *= mult;

ctx.putImageData( ctxData );
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top