后台设置
我有一个Web应用程序,用于处理从一组其他图像创建图像。我选择这样做的方法是通过读取一组图像并将它们放在HTML画布上。然后,我使用toDataURL
将每个画布作为jpeg导出到第三方API并将其转换为Blob。我面临的问题是,我有很多这些画布都将数据导出为jpg,并且消耗了大量资源。当每个画布尝试调用toDataURL
时,应用程序会变慢并变得无响应。
问题
我发现调用画布的toDataUrl()
或toBlob()
可能会非常慢,特别是对于大画布尺寸。我想利用Web worker的多线程特性。
首先,我尝试传入canvas对象但是抛出了一个错误。事实证明,对象是一个问题,它们似乎要么被转换为字符串,要么在无法克隆时失败。无论哪种方式,我发现传递上下文的图像数据确实有效。数据以原始RGB值的形式传递为画布上下文的方法Uint8ClampedArray
中的getImageData()
。
Main.js
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
var worker = new Worker('myWorker.js');
worker.postMessage({
image: context.getImageData(0, 0, canvas.width, canvas.height)
});
myWorker.js
this.onmessage = function(e) {
// GOAL: turn e.data.image into an image blob or dataUrl and return it.
// e.g. this.postMessage(new Blob([e.data.image.data], {type: 'image/jpg'});
}
我认为归结为知道如何将保存RGB信息的Uint8ClampedArray
转换为jpg / png数据。
我认为这可能有用的原因是我认为getImageData
只是从画布上下文中复制现有数据结构,因此不如toDataUrl
那么昂贵。我在调用类似于下面代码块的内容时捕获了cpu配置文件:
var image = context.getImageData(0, 0, canvas.width, canvas.height)
var dataUrl = canvas.toDataURL('image/jpeg');
得到了:
所以,考虑到这一点,我想把这个过程的主要负担转移到网络工作者身上。我甚至不介意,只要它在另一个进程中发生,它在Web工作者中需要更长的时间。
对此有一些额外的想法:
encoderOptions
toDataURL
中的第二个选项,以加快这一过程,但我没有看到太多变化答案 0 :(得分:6)
<强> ---- ---- UPDATE 强>
我以为我会以npm库的形式分享我的解决方案: https://www.npmjs.com/package/jpeg-web-worker。它解释了如何利用提供的网络工作者为您做繁重的工作。
<强> --------------------- 强>
我找到了一个适合我的解决方案,可以在生成新图像的同时加快应用程序和页面的响应速度。
以下是应用代码:
应用强>
var canvas = $('#myCanvas')[0];
var context = canvas.getContext('2d');
var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
var worker = new Worker('myWorker.js');
worker.postMessage({
image: imageData
});
worker.onmessage = function(e) {
var blob = new Blob( [e.data.data], {type: 'image/jpeg'} );
// use blob
}
这是工人代码:
<强>工人强>
this.onmessage = function(e) {
var jpgInfo = encode(e.data.image, 50);
this.postMessage(jpgInfo);
}
function encode() { ... } // ported from jpeg-js
显然,这个答案的大部分来自encode
函数。此功能已从npm模块jpeg-js进行了修改,更具体地说,是文件encoder.js。我通过将整个encoder.js文件复制到myWorker.js中来移植编码功能。它不是很小,但它也非常独立,这使它变得容易。我留下的唯一问题是修改代码,使其在为其构建的node.js环境之外工作。
事实证明这相对容易:
Buffer
的引用。这是一个两步的过程。首先,删除顶部的atob定义(因为它不需要)。其次,在this.encode函数的末尾返回new Unit8Array
。当前版本实际上已将此注释放在缓冲区引用的正上方。只需使用那个并删除下面的所有内容。我没有精确的定时测量,但是当图像生成到滞后时间的第二个时,它从延迟时间的~10秒开始。我在这里使用“滞后时间”意味着在使用页面时性能低下。