6

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

Dan Prince
  • 29,491
  • 13
  • 89
  • 120
  • @sebcap26 There is a fiddle. – easwee Feb 28 '14 at 15:22
  • 1
    @Dan Prince - maybe this question can give you some more info to solve this: http://stackoverflow.com/questions/7615009/disable-interpolation-when-scaling-a-canvas – easwee Feb 28 '14 at 15:23
  • Can you give some HTML / JS code ? – enguerranws Feb 28 '14 at 15:26
  • @enguerranws There's a lot of code, is there something you want to look at in specific? – Dan Prince Feb 28 '14 at 15:30
  • If I understand well, you want a pixellized result and not a smoothed one ? I can't test your image from here because of a stupid proxy, but when I run your fiddle with another image (https://ixquick.com/graphics/ixquick_res.gif) on firefox 27, the second canvas is not smoothed. – Sebastien C. Feb 28 '14 at 15:30
  • @sebcap26 That fiddle is just there to demonstrate that it's not a problem with my browser. That fiddle works for me, but something in my code doesn't. – Dan Prince Feb 28 '14 at 15:31
  • @Dan Prince We need a non working fiddle to help you. – Sebastien C. Feb 28 '14 at 15:34
  • I wanna check how you define "context", and what it is, as we can't see it now. – enguerranws Feb 28 '14 at 15:35
  • It's hard to tell what's wrong when you post working code and just say "my code doesn't work" :) –  Feb 28 '14 at 15:35
  • @sebcap26, zyklus I can't just put it in a fiddle, it's a full game engine which is loading local resources and json files over http. I can gist or fiddle any bits of code you want to see though. – Dan Prince Feb 28 '14 at 15:40
  • @enguerranws Canvas and Context creation is here: https://gist.github.com/code-curve/9273248 – Dan Prince Feb 28 '14 at 15:42
  • Partial progress, any suggestions on how I should be resizing my canvas? – Dan Prince Feb 28 '14 at 16:00

2 Answers2

3

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.

0

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 );