JSFiddle - React, Tailwind, and code Playground
HTML
<html lang="en">
<head>
<title>p h i l o u . c h</title>
</head>
<body style="background-color:#ccc;">
<canvas id="load-canvas" style="display:none;"></canvas>
<div>Bilinear Interpolation:<br>
<canvas id="disp-canvas" style="border: 1px solid red;"></canvas></div>
<div>Bicubic Interpolation:<br>
<canvas id="disp-canvas-bicubic" style="border: 1px solid green;"></canvas></div>
</body>
</html>
JavaScript
var BicubicInterpolation = (function(){
return function(x, y, values){
var i0, i1, i2, i3;
i0 = TERP(x, values[0][0], values[1][0], values[2][0], values[3][0]);
i1 = TERP(x, values[0][1], values[1][1], values[2][1], values[3][1]);
i2 = TERP(x, values[0][2], values[1][2], values[2][2], values[3][2]);
i3 = TERP(x, values[0][3], values[1][3], values[2][3], values[3][3]);
return TERP(y, i0, i1, i2, i3);
};
/* Yay, hoisting! */
function TERP(t, a, b, c, d){
return 0.5 * (c - a + (2.0*a - 5.0*b + 4.0*c - d + (3.0*(b - c) + d - a)*t)*t)*t + b;
}
})();
// compute vector index from matrix one
function ivect(ix, iy, w) {
// byte array, r,g,b,a
return((ix + w * iy) * 4);
}
function bilinear(srcImg, destImg, scale) {
// c.f.: wikipedia english article on bilinear interpolation
// taking the unit square, the inner loop looks like this
// note: there's a function call inside the double loop to this one
// maybe a performance killer, optimize this whole code as you need
function inner(f00, f10, f01, f11, x, y) {
var un_x = 1.0 - x; var un_y = 1.0 - y;
return (f00 * un_x * un_y + f10 * x * un_y + f01 * un_x * y + f11 * x * y);
}
var i, j;
var iyv, iy0, iy1, ixv, ix0, ix1;
var idxD, idxS00, idxS10, idxS01, idxS11;
var dx, dy;
var r, g, b, a;
for (i = 0; i < destImg.height; ++i) {
iyv = i / scale;
iy0 = Math.floor(iyv);
// Math.ceil can go over bounds
iy1 = ( Math.ceil(iyv) > (srcImg.height-1) ? (srcImg.height-1) : Math.ceil(iyv) );
for (j = 0; j < destImg.width; ++j) {
ixv = j / scale;
ix0 = Math.floor(ixv);
// Math.ceil can go over bounds
ix1 = ( Math.ceil(ixv) > (srcImg.width-1) ? (srcImg.width-1) : Math.ceil(ixv) );
...