Skip to content

Instantly share code, notes, and snippets.

@GoToLoop
Forked from gncgnc/resizeNN.js
Last active January 2, 2026 23:21
Show Gist options
  • Select an option

  • Save GoToLoop/2e12acf577506fd53267e1d186624d7c to your computer and use it in GitHub Desktop.

Select an option

Save GoToLoop/2e12acf577506fd53267e1d186624d7c to your computer and use it in GitHub Desktop.
Extends p5.Image to handle nearest neighbor resizing for scaling images w/o blurring.
/**
* Resize the image to a new width and height using nearest neigbor algorithm.
* To make the image scale proportionally, use 0 as the value for the wide or high parameters.
* For instance, to make the width of an image 150 pixels,
* and change the height using the same proportion, use resize(150, 0).
* Otherwise same usage as the regular resize().
*
* Note: Disproportionate resizing squashes the "pixels" from squares to rectangles.
* This works about 10 times slower than the regular resize.
* Any suggestions for performance increase are welcome.
*/
p5.Image.prototype.resizeNN = function (w, h) {
"use strict";
// Locally cache current image's canvas' dimension properties:
const {width, height} = this.canvas;
// Sanitize dimension parameters:
w = Math.round(Math.abs(w)), h = Math.round(Math.abs(h));
// Scale dimension parameters:
if (!(w | h)) w = width, h = height; // when both parameters are 0
else if (!w) w = h*width / height | 0; // when only w is 0
else if (!h) h = w*height / width | 0; // when only h is 0
const img = new p5.Image(w, h), // creates temporary image
sx = w / width, sy = h / height; // scaled coords. for current image
this.loadPixels(), img.loadPixels(); // initializes both 8-bit RGBa pixels[]
// Create 32-bit viewers for current & temporary 8-bit RGBa pixels[]:
const pixInt = new Uint32Array(this.pixels.buffer),
imgInt = new Uint32Array(img.pixels.buffer);
// Transfer current to temporary pixels[] by 4 bytes (32-bit) at once:
for (let y = 0; y < h; ) {
const curRow = width * ~~(y/sy), tgtRow = w * y++;
for (let x = 0; x < w; ) {
const curIdx = curRow + ~~(x/sx), tgtIdx = tgtRow + x++;
imgInt[tgtIdx] = pixInt[curIdx];
}
}
img.updatePixels(); // updates temporary 8-bit RGBa pixels[] w/ its current state
// Resize current image to temporary image's dimensions:
this.canvas.width = this.width = w, this.canvas.height = this.height = h;
this.drawingContext.drawImage(img.canvas, 0, 0, w, h, 0, 0, w, h);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment