Search code examples
compressionstoragetyped-arraystransmission

How Compress TypedArrays/ArrayBuffers for storage and transmission


We started using images for convenient storage of TypedArrays via the ImageData object of canvas. But this fails due to pre-multiplying .. limiting us to 24 bits of data. We're limping along with this but would love a 32 bit solution.

We want to convert to use of any TypedArray or its ArrayBuffer. But these suffer from lack of compression.

Any interesting ways to compress them? LZMA-JS? JSzip? Figure out how to make non-premultiplied pngs? Other?


Solution

  • ImageData will provide you with 32-bits (RGB + alpha channel). The pre-multipling part refer to the alpha channel and the rounding errors due to integer values being used (there is no way around this unless you want to make a custom floating point based bitmap, which is possible but slow(er)). You would still get 32-bit data but with some rounding errors here and there.

    For the data you could then use the Pako implementation of the zlib port for JavaScript. It's fast and 100% compatible with the original implementation result-wise, and offers good compression.

    It returns an Uint8Array which can be converted to a Blob or ArrayBuffer for storage with f.ex. IndexedDB or transferred over the net.

    Example usage

    Compress data:

    // assuming CORS requirements are fulfilled:
    var data = ctx.getImageData(x, y, width, height).data;
    var comp = pako.deflate(data);
    

    Decompress data:

    try {
      var data = pako.inflate(comp);
      var idata = new ImageData(width, height); // or via getImageData()
      idata.data.set(data);
      ctx.putImageData(idata, x, y);
    }
    catch (err) {
      console.log(err);
    }