在主线程中:我通过getImageData方法获取源图像数组。它是一个uint8ClampedArray来记录我的图像数据。
这是我在web worker中的代码: (这段代码会给我一个高分辨率的图像,但操作的结果太大了)
self.addEventListener('message', function(e){
var scale = e.data['scale'], cvWidth = e.data['width'], cvHeight = e.data['height'], sBufferData = e.data['sBuffer'].data;
var sq = scale*scale, //pixel of source within target
sw = cvWidth, sh = cvHeight,
sx = 0, sy = 0, sIdx = 0,
tw = Math.floor(sw * scale), th = Math.floor(sh * scale),
tx = 0, ty = 0, tIdx = 0,
TX = 0, TY = 0, yIdx = 0,
w = 0, nw = 0, wx = 0, nwx = 0, wy = 0, nwy = 0,
sR = 0, sG = 0, sB = 0,
crossX = false, crossY = false,
tBuffer = new Float32Array(3 * sw * sh);
for( sy=0; sy<sh; sy++ ) {
ty = sy * scale; TY = 0 | ty; yIdx = 3 * TY * tw; crossY = (TY != (0 | ty + scale));
if(crossY) { wy = (TY + 1 - ty); nwy = (ty + scale - TY - 1); }
for( sx=0; sx<sw; sx++, sIdx+=4 ) {
tx = sx * scale; TX = 0 | tx; tIdx = yIdx + TX * 3; crossX = (TX != (0 | tx + scale));
if(crossX) { wx = (TX + 1 - tx); nwx = (tx + scale - TX - 1); }
sR = sBufferData[sIdx+0]; sG = sBufferData[sIdx+1]; sB = sBufferData[sIdx+2];
if(!crossX && !crossY) {
tBuffer[tIdx+0] += sR * sq; tBuffer[tIdx+1] += sG * sq; tBuffer[tIdx+2] += sB * sq;
} else if(crossX && !crossY) {
w = wx * scale;
tBuffer[tIdx+0] += sR * w; tBuffer[tIdx+1] += sG * w; tBuffer[tIdx+2] += sB * w;
nw = nwx * scale
tBuffer[tIdx+3] += sR * nw; tBuffer[tIdx+4] += sG * nw; tBuffer[tIdx+5] += sB * nw;
} else if(crossY && !crossX) {
w = wy * scale;
tBuffer[tIdx+0] += sR * w; tBuffer[tIdx+1] += sG * w; tBuffer[tIdx+2] += sB * w;
nw = nwy * scale
tBuffer[tIdx+3 * tw+0] += sR * nw; tBuffer[tIdx+3 * tw+1] += sG * nw; tBuffer[tIdx+3 * tw+2] += sB * nw;
} else {
w = wx * wy;
tBuffer[tIdx+0] += sR * w; tBuffer[tIdx+1] += sG * w; tBuffer[tIdx+2] += sB * w;
nw = nwx * wy; //for TX + 1; TY px
tBuffer[tIdx+3] += sR * nw; tBuffer[tIdx+4] += sG * nw; tBuffer[tIdx+5] += sB * nw;
nw = nwy * wx;
tBuffer[tIdx+3 * tw+0] += sR * nw; tBuffer[tIdx+3 * tw+1] += sG * nw; tBuffer[tIdx+3 * tw+2] += sB * nw;
nw = nwx * nwy;
tBuffer[tIdx+3 * tw+3] += sR * nw; tBuffer[tIdx+3 * tw+4] += sG * nw; tBuffer[tIdx+3 * tw+5] += sB * nw;
}
}
}
var worker2Object = {'tBuffer': tBuffer}; //I guess tBuffer is too Large
tBuffer = undefined; e = undefined;
self.postMessage(worker2Object); //Return to Main Thread
}, false);
当我使用 IE或FireFox (Chrome很好)时,网络工作线程中内存不足。
但是当图像尺寸小于1MB时,可以在3种浏览器上工作。
因此我怀疑问题是操作的结果(tBuffer)太大。 任何人都可以帮我解决这个问题吗?谢谢你的帮助。
我需要将big-O(n ^ 2)算法移动到web worker,然后它不会阻止我的主线程来执行其他脚本。
现在,我需要在5个web worker 线程中扩展 5规格图像。程序代码
for( var i in 5 spec image size array ) { //LOOP 5 time and new 5 web workers
//get imageData of source image
sourceBuffer = canvas.getContext("2d").getImageData(0, 0, w, h);
//new Worker_1 to process spec_1 image and so on
Worker_1 = new Worker('myWebWorker.js');
Worker_1.postMessage(sourceBuffer);
Worker_1.onmessage = function(e){ get e.data }
}
答案 0 :(得分:2)
嗯,这是一个想法 - 当你使用Float32Array时,记住每个颜色分量从8位(1字节)大小转换为32位大小(4字节)。
因此,如果您的图像是,为简单起见,假设1000x1000,则内存消耗为:
Normal canvas:
1000 x 1000 x 4 = 4,000,000 bytes or 3.8 mb
如果是32位浮点数组,则大小为:
Float32Array:
1000 x 1000 x 16 = 16,000,000 bytes or 15.3 mb
现在将其与5相乘(假设每个工作在图像或图像上具有相同的大小),并且使用float32初始的3.8 mb画布(原始数据)将为76.5 mb。
如果你的图像更多的是在2000 x 2000的泳道中,那么你的画布为305 mb + 15 mb,或者4000 x 4000然后是1.2 gb(!)+ 61 mb的画布等等。
此外:原始大小仅适用于您可以访问的缓冲区。浏览器可能有也可能没有该数据的后台缓冲区,这意味着在后一种情况下,您将大大超过千兆字节大小,这可以很容易地解释内存不足错误消息。
如果你需要高精度的色彩处理(我假设你使用浮子),可以选择:
提示:如果对工作人员使用transferable objects,您将获得巨大的性能提升。