1

I work with emscripten where I create a bitmap in C++ which I pass to my javascript code

const int COMP = 4;
long createBitmap(int DIM)
{
    srand(NULL);
    // create buffer
    long buffer = EM_ASM_INT(
    {
        var buffer = Module._malloc($0 * 1);
        return buffer;
    }, DIM*DIM*COMP);

    uint8_t* bitmap = (uint8_t*)buffer;

    //just randomly fill the buffer
    for (int i = 0; i < DIM*DIM*COMP; i++)
    {
        if (i%4==3)
            bitmap[i] = 128;
        else
            bitmap[i] = rand()%256;
    }

    return buffer;
}

and in javascript I have the following code:

var dim = 1080;
var buffer = Module.createBitmap(dim);
var c = document.getElementById("bitmap");
var ctx = c.getContext("2d");
var imgData = ctx.createImageData(dim,dim);
for (var i = 0; i < dim*dim*4; i++) {
    imgData.data[i] = Module.HEAPU8[buffer+i];
}

ctx.putImageData(imgData, 0, 0)

This works well but I don't like the loop to assign all the elements of the buffer to the imgData.data array. I know that the uint8_t data type that I use in C++ corresponds to the Uint8ClampedArray for imgData.data. To me this seems like a good opportunity to just assign the beginning of the buffer to this imgData.data and I won't have to copy anything - is this possible?

Philipp
  • 2,376
  • 5
  • 29
  • 47
  • Is `buffer` a `Uint8ClampedArray`? – guest271314 Nov 11 '16 at 08:06
  • There's [`copyWithin()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/copyWithin) but IE doesn't support it. – Ouroborus Nov 11 '16 at 08:07
  • @guest271314 buffer is the location of the beginning of a Uint8ClampedArray. – Philipp Nov 11 '16 at 08:17
  • @Philipp See also [createImageBitmap alternative on Safari](http://stackoverflow.com/questions/40094245/createimagebitmap-alternative-on-safari/) – guest271314 Nov 11 '16 at 08:21
  • @guest271314 this looks nice but the problem with this is that `buffer` is not an `ArrayBuffer` it is just a number pointing to the right memory location. Can I somehow cast this to an `ArrayBuffer`? Right now I get `createAndDisplayBitmap.html:18 Uncaught DOMException: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width).` with this approach. – Philipp Nov 11 '16 at 08:24
  • What is issue with using existing `for` loop at `javascript`? – guest271314 Nov 11 '16 at 08:37
  • Performance - I expect to get many bitmaps per second eventually and will draw them. Having then to loop every time through each bitmap and copy the contents will be a bottleneck. – Philipp Nov 11 '16 at 08:44
  • What is `Module.HEAPU8`? – guest271314 Nov 11 '16 at 08:49
  • This is a memory view provided by emscripten: https://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html it views the memory pointed by the buffer as 8-bit unsigned memory. – Philipp Nov 11 '16 at 08:52
  • Have not tried `emscripten`. How is `imgData` assigned value from `Module.HEAPU8`? is `Module.HEAPU8` an array? – guest271314 Nov 11 '16 at 09:07

1 Answers1

2

I've gotten this answer from the emscripten google group.

The answer is actually quite simple.

var mappedBuffer= new Uint8ClampedArray(Module.HEAPU8.buffer, buffer, dim * dim * 4)

So HEAPU8.buffer accesses the underlying buffer and with that I can create an Uint8ClampedArray typed array.

Then you can simply write

imgData.data.set(mappedBuffer)
ctx.putImageData(imgData, 0, 0)
Philipp
  • 2,376
  • 5
  • 29
  • 47