Pixel Interpolation

Benchmark created by Daniel G. Taylor on


Description

Compare methods to do canvas pixel interpolation. Compares stuff like nearest-neighbor, bilinear, etc and various optimizations.

Preparation HTML

<canvas id="canvas" width="100" height="100"></canvas>

Setup

var canvas = document.getElementById('canvas');
    var context = canvas.getContext('2d');
    var imageData = context.getImageData(0, 0, 100, 100);
    var red, green, blue;
    
    function nearest(pixels, x, y, offset, width) {
        return pixels[offset + Math.round(y) * width * 4 + Math.round(x) * 4];
    }
    
    function nearest_unrolled(pixels, x, y, width) {
        var yw4x4 = ((y + 0.5) ^ 0) * width * 4 + ((x + 0.5) ^ 0) * 4;
        return [
            pixels[yw4x4],
            pixels[yw4x4 + 1],
            pixels[yw4x4 + 2]
        ]
    }
    
    function bilinear(pixels, x, y, offset, width) {
        var percentX = 1.0 - (x - Math.floor(x));
        var percentY = y - Math.floor(y);
    
        var top = pixels[offset + Math.ceil(y) * width * 4 + Math.floor(x) * 4] * percentX + pixels[offset + Math.ceil(y) * width * 4 + Math.ceil(x) * 4] * (1.0 - percentX);
        var bottom = pixels[offset + Math.floor(y) * width * 4 + Math.floor(x) * 4] * percentX + pixels[offset + Math.floor(y) * width * 4 + Math.ceil(x) * 4] * (1.0 - percentX);
    
        return top * percentY + bottom * (1.0 - percentY);
    }
    
    function bilinear_optimized(pixels, x, y, offset, width) {
        var percentX = x - (x | 0);
        var percentX1 = 1.0 - percentX;
        var percentY = y - (y | 0);
        var cx4 = ((x === ~~x) ? x : x + 1 | 0) * 4;
        var fx4 = (x | 0) * 4;
        var cy4 = ((y === ~~y) ? y : y + 1 | 0) * 4;
        var fy4 = (y | 0) * 4;
        var cy4wo = cy4 * width + offset;
        var fy4wo = fy4 * width + offset;
    
        var top = pixels[cy4wo + fx4] * percentX1 + pixels[cy4wo + cx4] * percentX;
        var bottom = pixels[fy4wo + fx4] * percentX1 + pixels[fy4wo + cx4] * percentX;
    
        return top * percentY + bottom * (1.0 - percentY);
    }
    
    function bilinear_unrolled(pixels, x, y, width) {
        var percentX = x - (x | 0);
        var percentX1 = 1.0 - percentX;
        var percentY = y - (y | 0);
        var percentY1 = 1.0 - percentY;
        var cx4 = ((x === ~~x) ? x : x + 1 | 0) * 4;
        var fx4 = (x | 0) * 4;
        var cy4 = ((y === ~~y) ? y : y + 1 | 0) * 4;
        var fy4 = (y | 0) * 4;
        var cy4wr = cy4 * width;
        var fy4wr = fy4 * width;
        var cy4wg = cy4wr + 1;
        var fy4wg = fy4wr + 1;
        var cy4wb = cy4wr + 2;
        var fy4wb = fy4wr + 2;
        var top, bottom, r, g, b;
    
        top = pixels[cy4wr + fx4] * percentX1 + pixels[cy4wr + cx4] * percentX;
        bottom = pixels[fy4wr + fx4] * percentX1 + pixels[fy4wr + cx4] * percentX;
        r = top * percentY + bottom * percentY1;
        
        top = pixels[cy4wg + fx4] * percentX1 + pixels[cy4wg + cx4] * percentX;
        bottom = pixels[fy4wg + fx4] * percentX1 + pixels[fy4wg + cx4] * percentX;
        g = top * percentY + bottom * percentY1;
        
        top = pixels[cy4wb + fx4] * percentX1 + pixels[cy4wb + cx4] * percentX;
        bottom = pixels[fy4wb + fx4] * percentX1 + pixels[fy4wb + cx4] * percentX;
        b = top * percentY + bottom * percentY1;
    
        return [r, g, b];
    }

Test runner

Ready to run.

Testing in
TestOps/sec
Nearest Neighbor
var red = nearest(imageData.data, 10.2, 4.6, 0, canvas.width);
var green = nearest(imageData.data, 10.2, 4.6, 1, canvas.width);
var blue = nearest(imageData.data, 10.2, 4.6, 2, canvas.width);
ready
Nearest Neighbor Optimized Unrolled
var rgb = nearest_unrolled(imageData.data, 10.2, 4.6, canvas.width);
ready
Bilinear
var red = bilinear(imageData.data, 10.2, 4.6, 0, canvas.width);
var green = bilinear(imageData.data, 10.2, 4.6, 1, canvas.width);
var blue = bilinear(imageData.data, 10.2, 4.6, 2, canvas.width);
ready
Bilinear Optimized
var red = bilinear_optimized(imageData.data, 10.2, 4.6, 0, canvas.width);
var green = bilinear_optimized(imageData.data, 10.2, 4.6, 1, canvas.width);
var blue = bilinear_optimized(imageData.data, 10.2, 4.6, 2, canvas.width);
ready
Bilinear Optimized Unrolled
var rgb = bilinear_unrolled(imageData.data, 10.2, 4.6, canvas.width);
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.