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

rvi*_*hne 4 javascript optimization canvas 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);
Run Code Online (Sandbox Code Playgroud)

但是速度比较慢。我的理论是为什么:

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

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

这些理论是否正确,如果正确,我可以采用什么技巧来尽快完成?我愿意接受特定于浏览器的答案。

Kai*_*ido 5

不,您的 ImageDataimage和 TypedArray array共享完全相同的 buffer 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);
Run Code Online (Sandbox Code Playgroud)

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