简体   繁体   中英

What is the best way, to draw a part of an arraybuffer to the canvas?

I have an ArrayBuffer , and I have a function called module.repaint, which works with the ArrayBuffer. In every redraw call, I would like to put the colors from the ArrayBuffer to the canvas.

I do it like this:

imgData.data.set(new Uint8ClampedArray(MEM, 0, siz));

But is it possible, to copy a part of the ArrayBuffer to an other faster? Code:

var MEM = new ArrayBuffer(2*1024*1024);
var canvas, ctx, imgData, siz;

var repaint = function() {
    // module.repaint works on the arraybuffer
    module.repaint();

    imgData.data.set(new Uint8ClampedArray(MEM, 0, siz));
    ctx.putImageData(imgData, 0, 0);

    requestAnimationFrame(repaint);
};

var init = function() {
    canvas = document.getElementById('canvas');
    ctx = canvas.getContext('2d');

    siz = canvas.width*canvas.height*4;

    imgData=ctx.createImageData(canvas.width,canvas.height);

    repaint();
};

If possible, refactor your module.repaint() to use an offscreen canvas instead of a pixel array.

That way you can just drawImage the offscreen canvas to the onscreen canvas--efficient because the GPU can do the blitting instead of burdening the CPU.

putImageData is slower because it involves the CPU fetching data from the pixel array, setting that data in your temp array and transferring the temp array to the onscreen imageData. These are all activities that burden the CPU and reduce performance.

Note that I didn't check if the gain is important, but I can see some useful optimizations here.

First, Uint8ClampedArray is a view to the buffer, not a buffer itself, so you don't need to create it everytime. (You can also have multiple views on a single buffer)

You should also avoid using the set method of imgData.data because it copies all the data from one array to another (which is useless). Instead, you can set your Uint8ClampedArray on the constructor.

With that code, each change on MEM will automatically affect imgData because imgData.data directly points to MEM .

var MEM = new ArrayBuffer(2*1024*1024);
var canvas, ctx, imgData, siz;

var repaint = function() {
    // module.repaint works on the arraybuffer
    module.repaint();

    ctx.putImageData(imgData, 0, 0);

    requestAnimationFrame(repaint);
};

var init = function() {
    canvas = document.getElementById('canvas');
    ctx = canvas.getContext('2d');

    siz = canvas.width*canvas.height*4;

    imgData = ctx.createImageData(new Uint8ClampedArray(MEM, 0, siz), canvas.width, canvas.height);

    repaint();
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM