将ArrayBuffer转换为ImageData以在画布上绘图:优化

时间:2016-09-21 03:18:19

标签: javascript canvas optimization arraybuffer putimagedata

我通过以原始ImageData格式发送每个帧(RGBA顺序中每个像素4个字节),通过WebSocket传输视频。当我在客户端上收到每个帧时(作为ArrayBuffer),我想使用putImageData尽可能高效地将此图像直接绘制到画布上。

这是我目前的解决方案:

// buffer is an ArrayBuffer representing a properly-formatted image
var array = new Uint8ClampedArray(buffer);
var image = new ImageData(array, width, height);
canvas.putImageData(image, 0, 0);

但它很慢。我的理论为什么:

  • 数组(大小约为1MB)被复制三次,一次进入Uint8ClampedArray,一次进入ImageData,最后进入画布,每帧(30次)每秒)。

  • 我每帧使用new两次,这可能是垃圾收集器的问题。

这些理论是否正确?如果是这样,我可以采用哪些技巧来尽快实现这一目标?我愿意接受特定于浏览器的答案。

1 个答案:

答案 0 :(得分:3)

不,您的ImageData image和TypedArray array共享完全相同的缓冲区buffer

这些只是指针,您的原始缓冲区永远不会被“复制”。

var ctx = document.createElement('canvas').getContext('2d');

var buffer = ctx.getImageData(0,0,ctx.canvas.width, ctx.canvas.height).data.buffer;

var array = new Uint8ClampedArray(buffer);

var image = new ImageData(array, ctx.canvas.width, ctx.canvas.height);

console.log(array.buffer === buffer && image.data.buffer === buffer);

对于处理时间问题,最好的方法是直接将视频流直接发送到videoElement并使用drawImage