HTML5如何将PNG缓冲区加载到画布中(用于流媒体目的)

7

通过websocket,我得到了一个以PNG格式为基础的二进制图像缓冲区(类似于此处这样)。

我想将此PNG缓冲区加载到画布中,然后读取不同的像素以读取未压缩的数据。

我设法做到了,但这很愚蠢:

function onBinaryMessage(/*ArrayBuffer*/ input) {
  input = new Uint8Array(input);

  var str = '';
  for (var i = 0; i < input.byteLength; i++)
    str = str + String.fromCharCode(input[i]);

  var image = document.getElementById("image");
  image.src = 'data:image/png;base64,' + btoa(str);

  var c = document.getElementById("canvas");
  var ctx = c.getContext("2d");
  ctx.drawImage(image, 0, 0);
  var imgData = ctx.getImageData(0, 0, image.width, image.height);
  console.log(imgData);
}

我需要将二进制数据转换成字符串,以便对该字符串进行base64编码,然后将这个新生成的base64字符串赋值给我的图片src属性... 浏览器需要重新将这个base64编码数据转换回我得到的原始PNG缓冲区...
有没有直接设置画布缓冲区的方法? 或者有没有更好的流处理方法?
我认为可以使用File API将缓冲区写入临时文件,但创建文件的成本很高 :(
有什么建议吗?
1个回答

10
您可以将输入缓冲区转换为 Blob,获取其 URL 并使用该 URL 代替在画布上绘制:
function onBinaryMessage(input) {

    var blob = new Blob([input], {type: 'image/png'});
    var url = URL.createObjectURL(blob);
    var img = new Image;

    img.onload = function() {
        var ctx = document.getElementById("canvas").getContext('2d');
        ctx.drawImage(this, 0, 0);
        URL.revokeObjectURL(url);
    }
    img.src = url;
}

请注意,这将是异步的,您需要在onload处理程序内提供回调机制(无论如何,在您自己的示例中也需要这样做)。但是,您不必转换为base64等,这是一个相对昂贵的操作。
另请注意,URL.createObjectURL目前处于实验阶段。

非常感谢,它运行得非常好。我几个小时前刚找到答案,但你回答得比我快,而且你的答案更好,因为你没有创建一个图像dom元素。createObjectURL非常好用,我可以使用FileReader和readAsDataURL。但是createObjectURL必须更快,并且它是同步调用。非常好的答案,非常感谢 ;)然而canvas仍然是一个dom元素,我希望我能像你刚才写的新Image一样使用一个新的Canvas。(dom很邪恶) - Gb01
@Gb01好消息,你也可以这样使用canvas。只需使用var canvas = document.createElement('canvas');,无需将其附加到DOM(当然,像图像一样,它仍然是一个DOM元素)。很高兴我能帮到你! :) - user1693593
非常感谢您提到revokeObjectURL()! 在看到您的回答之前,我并没有意识到blob不会自动进行垃圾回收。 - Klesun

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接