HTML5 canvas: is there a way to resize image with "nearest neighbour" resampling?

10,491

Solution 1

image-rendering: -webkit-optimize-contrast; /* webkit */
image-rendering: -moz-crisp-edges /* Firefox */

http://phrogz.net/tmp/canvas_image_zoom.html can provide a fallback case using canvas and getImageData. In short:

// Create an offscreen canvas, draw an image to it, and fetch the pixels
var offtx = document.createElement('canvas').getContext('2d');
offtx.drawImage(img1,0,0);
var imgData = offtx.getImageData(0,0,img1.width,img1.height).data;

// Draw the zoomed-up pixels to a different canvas context
for (var x=0;x<img1.width;++x){
  for (var y=0;y<img1.height;++y){
    // Find the starting index in the one-dimensional image data
    var i = (y*img1.width + x)*4;
    var r = imgData[i  ];
    var g = imgData[i+1];
    var b = imgData[i+2];
    var a = imgData[i+3];
    ctx2.fillStyle = "rgba("+r+","+g+","+b+","+(a/255)+")";
    ctx2.fillRect(x*zoom,y*zoom,zoom,zoom);
  }
}

More: MDN docs on image-rendering

Solution 2

I wrote a NN resizing script a while ago using ImageData (around line 1794)

https://github.com/arahaya/ImageFilters.js/blob/master/imagefilters.js

You can see a demo here

http://www.arahaya.com/imagefilters/

unfortunately the builtin resizing should be slightly faster.

Share:
10,491
ABTOMAT
Author by

ABTOMAT

Updated on June 05, 2022

Comments

  • ABTOMAT
    ABTOMAT almost 2 years

    I have some JS that makes some manipulations with images. I want to have pixelart-like graphics, so I had to enlarge original images in graphics editor. But I think it'd be good idea to make all the manipulations with the small image and then enlarge it with html5 functionality. This will save bunch of processing time (because now my demo (warning: domain-name may cause some issues at work etc) loads extremely long in Firefox, for example). But when I try to resize the image, it gets resampled bicubically. How to make it resize image without resampling? Is there any crossbrowser solution?

  • ABTOMAT
    ABTOMAT over 12 years
    Thought about that, but won't it be very slow?
  • Simon Sarris
    Simon Sarris over 12 years
    In short, yeah. It will be very slow. There's another way I can think of involving an in-memory canvas and a large amount of drawImage calls but it may not be consistent across browser because of anti-aliasing differences and may not be much faster.
  • Polyducks
    Polyducks over 6 years
    A comment for future readers: CSS image optimising will round to the nearest pixel, which may not always be ideal for your images. Your space invaders may become lumpy and Mario may be deformed. Best to use the code method detailed above - or enlarge your images x3 so that the effects of binomial image-rendering are negligable.
  • PinkTurtle
    PinkTurtle almost 2 years
    > pixelated