【发布时间】:2015-04-20 23:44:11
【问题描述】:
我正在尝试构建一个简单的基于 HTML5 画布的图像处理器,它获取图像并生成它的平铺版本,每个平铺是底层图像区域的平均颜色。
这很容易在 Web Worker 的上下文之外执行,但我想使用一个 worker,以免阻塞 ui 处理线程。数据采用的 Uint8ClampedArray 形式让我对如何逐块处理它感到头疼。
下面是一个 plunk,展示了我到目前为止所做的事情以及它是如何不起作用的。
http://plnkr.co/edit/AiHmLM1lyJGztk8GHrso?p=preview
相关代码在worker.js中
这里是:
onmessage = function (e) {
var i,
j = 0,
k = 0,
data = e.data,
imageData = data.imageData,
tileWidth = Math.floor(data.tileWidth),
tileHeight = Math.floor(data.tileHeight),
width = imageData.width,
height = imageData.height,
tile = [],
len = imageData.data.length,
offset,
processedData = [],
tempData = [],
timesLooped = 0,
tileIncremented = 1;
function sampleTileData(tileData) {
var blockSize = 20, // only visit every x pixels
rgb = {r:0,g:0,b:0},
i = -4,
count = 0,
length = tileData.length;
while ((i += blockSize * 4) < length) {
if (tileData[i].r !== 0 && tileData[i].g !== 0 && tileData[i].b !== 0) {
++count;
rgb.r += tileData[i].r;
rgb.g += tileData[i].g;
rgb.b += tileData[i].b;
}
}
// ~~ used to floor values
rgb.r = ~~(rgb.r/count);
rgb.g = ~~(rgb.g/count);
rgb.b = ~~(rgb.b/count);
processedData.push(rgb);
}
top:
for (; j <= len; j += (width * 4) - (tileWidth * 4), timesLooped++) {
if (k === (tileWidth * 4) * tileHeight) {
k = 0;
offset = timesLooped - 1 < tileHeight ? 4 : 0;
j = ((tileWidth * 4) * tileIncremented) - offset;
timesLooped = 0;
tileIncremented++;
sampleTileData(tempData);
tempData = [];
//console.log('continue "top" loop for new tile');
continue top;
}
for (i = 0; i < tileWidth * 4; i++) {
k++;
tempData.push({r: imageData.data[j+i], g: imageData.data[j+i+1], b: imageData.data[j+i+2], a: imageData.data[j+i+3]});
}
//console.log('continue "top" loop for new row per tile');
}
postMessage(processedData);
};
我确信有一种更好的方法可以从标记的 for 循环开始完成我正在尝试做的事情。因此,任何替代方法或建议将不胜感激。
更新:
我采取了不同的方法来解决这个问题:
http://jsfiddle.net/TunMn/425/
关闭,但没有。
我知道问题出在哪里,但我不知道如何修改它。同样,我们将不胜感激任何帮助。
【问题讨论】:
标签: javascript html image canvas web-worker