Safari上的createImageBitmap替代方案

7

我希望能够在一个运行在Web Worker上的asm.js代码中生成图像。并且我希望定期将该计算的最新状态与其他内容一起合成到用户可见的2D画布上。目前,我已经有了这样的代码。

  1. 使用其构造函数,基于asm.js代码使用的数组缓冲区的一部分,构建ImageData对象。
  2. 调用createImageBitmapImageData转换为ImageBitmap
  3. 传输该图像位图从工作线程到GUI线程,并
  4. 将该ImageBitmap用作CanvasRenderingContext2D.drawImage的参数。
近期的Chrome和Firefox表现良好,但是Safari 9.1.3显然没有createImageBitmap函数。有什么方法可以在Safari上实现类似的功能呢?是否有一些低成本的图像编码方式,而不是为其创建data:image/png…?是否有其他方法将字节数组转换为可以馈送给drawImage的内容?顺便说一句:http://caniuse.com/目前未列出此功能。有一个功能请求,如果您希望在那里监视此功能,则可以使用它。
如果您想查看我的当前方法的代码,请看我的工作者的相关部分:
var buffer = new ArrayBuffer(bufferSize);
var asm = Module.asm(self, {}, buffer);
var imgBytes = new Uint8ClampedArray(buffer, offset);
var imgData = new ImageData(imgBytes, width, height);
createImageBitmap(imgData).then(function(bmp) { // Not available on Safari!
    postMessage(bmp, [bmp]);
});

这里是相应的GUI线程代码:

var worker = new Worker(‹url of worker›);
worker.onmessage = function(msg) {
    var img = msg.data;
    context2d.drawImage(img, 0, 0, width, height);
};

实际的完整代码在this GitHub pull request中,但是还有很多其他与问题无关的内容。
1个回答

5
有没有其他方法可以将字节数组转换为可以传递给drawImage的内容?
您可以将Uint8ClampedArray对象的ArrayBuffer发布到主线程;在主线程中,使用.putImageData()替代.drawImage()。正如@Kaiido所指出的那样,在Worker中创建ImageData对象是不必要的。
var imgBytes = new Uint8ClampedArray(buffer, offset);
postMessage(imgBytes.buffer, [imgBytes.buffer]);

在主线程

worker.onmessage = function(e) {
  console.log(e.data); // `ArrayBuffer`
  ctx.putImageData(new ImageData(new Uint8ClampedArray(e.data), width, height), 0, 0);
}

http://plnkr.co/edit/N0v1YQHQX2rdFfHcOKeR?p=preview


这将从PNG文件中加载图像。因此,虽然它存储在类型化数组中,但它不是原始像素数据。如果我要复制这种方法,我可能需要对像素数据进行PNG编码,这需要一些时间,并且需要一些库或自编写的PNG头、行头插入和最小化的deflate编码(例如仅使用未压缩的存储方法)。尽管如此,这可能是一个可行的选择,特别是如果没有更好的选择出现,所以谢谢! - MvG
@MvG 你可以选择在 postMessage 中传输 imgDatabuffer 到主线程,使用 .putImageData 替代 .drawImage;请参见更新的帖子。 - guest271314
1
如果我理解正确的话,对于你最后部分,你不需要在worker中创建一个ImageData对象。(https://jsfiddle.net/Kaiido/234ekx4b/) - Kaiido
@Kaiido 是的,你说得对。http://plnkr.co/edit/N0v1YQHQX2rdFfHcOKeR?p=preview - guest271314
1
这听起来很有趣。由于我需要与其他内容合成,所以我需要使用drawImage,但是我可以将putImageData放到离屏画布中,然后将其绘制到主画布上。 - MvG

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