How to resize a canvas without anti-aliasing?

喜夏-厌秋 提交于 2019-12-21 13:05:30

问题


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.

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.

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

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


回答1:


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.




回答2:


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


来源:https://stackoverflow.com/questions/22098953/how-to-resize-a-canvas-without-anti-aliasing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!