1

I have written the following webworker which will process an image and add bilinear interpolation to the upscaled version.

This works great for making images larger however I need to now make images smaller.

My understanding is that Interpolation is for upscaling not downsizing.

this.addEventListener('message', function(event) {

    var src = event.data.imageData,
        dest = event.data.imageDataNew

        postMessage({
            'imageData':bilinear(src, dest, scale)
        });

}, false);

  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) );
                idxD = ivect(j, i, destImg.width);
                // matrix to vector indices
                idxS00 = ivect(ix0, iy0, srcImg.width);
                idxS10 = ivect(ix1, iy0, srcImg.width);
                idxS01 = ivect(ix0, iy1, srcImg.width);
                idxS11 = ivect(ix1, iy1, srcImg.width);
                // overall coordinates to unit square
                dx = ixv - ix0; dy = iyv - iy0;
                // I let the r, g, b, a on purpose for debugging
                r = inner(srcImg.data[idxS00], srcImg.data[idxS10],
                    srcImg.data[idxS01], srcImg.data[idxS11], dx, dy);
                destImg.data[idxD] = r;

                g = inner(srcImg.data[idxS00+1], srcImg.data[idxS10+1],
                    srcImg.data[idxS01+1], srcImg.data[idxS11+1], dx, dy);
                destImg.data[idxD+1] = g;

                b = inner(srcImg.data[idxS00+2], srcImg.data[idxS10+2],
                    srcImg.data[idxS01+2], srcImg.data[idxS11+2], dx, dy);
                destImg.data[idxD+2] = b;

                a = inner(srcImg.data[idxS00+3], srcImg.data[idxS10+3],
                    srcImg.data[idxS01+3], srcImg.data[idxS11+3], dx, dy);
                destImg.data[idxD+3] = a;
            }
        }

        return destImg;
    }

I have also written a Lancosz webworker which produces great results but is far to slow. What I am looking for is something inbetween.

Does anyone know of a good reasonably fast javascript implementation of a Bilinear/Bicubic downsizing filter?

The kind of images I will be dealing with may be as large as 5000x5000 and will be downsized to 1000x1000.

As long as performance is less than around 10 seconds or so it will be fine.

2
  • and scaling the image down with the native canvas drawImage isn't acceptable? Commented Nov 9, 2012 at 16:46
  • Unfortunately no, the reduced images look quite poor when going from 5000x5000px to 1000x1000px Commented Nov 9, 2012 at 17:07

1 Answer 1

2

I have seen very good results in pure Javascript image resize by Grant Galitz

https://github.com/taisel/JS-Image-Resizer

(Author of Gameboy Color emulator in JS)

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.