使用Web工作程序问题在Canvas上进行位图过滤

Chr*_*ich 1 javascript video canvas

我有一个视频将像素复制到画布并使用web worker应用实时位图过滤器.

使用网络工作者时,我无法在画布上看到结果发生的变化(应该是黑色的'白色).

这是我的代码:http: //www.dev.createdbychristian.com/filter-test/

我可以通过使用中间画布来解决这个问题,但我真的不想那样做.

我的代码松散地基于这个例子,就像我刚刚没有使用web worker进行图像过滤处理一样. http://techslides.com/demos/html5-video-canvas.html

我的代码出了什么问题?

注意:需要一个支持Web Workers和HTML5 Video/canvas的现代浏览器

Zet*_*eta 6

发生这种情况是因为draw()不等待WebWorker的返回值并使用requestAnimationFrame.如果您想要连续过滤的图像draw,则必须在应用过滤器后调用:

filterWorker.addEventListener('message', function(e) {
    ctx.putImageData(e.data, 0, 0);
    requestAnimationFrame(draw);
}, false);
Run Code Online (Sandbox Code Playgroud)

但是,如果过滤器需要很长时间,很可能draw会在早期注意到更改时用彩色数据填充画布(我能够在当前版本中看到带有FF17的黑色'n白色版本).

我的代码出了什么问题?

在操作顺序很重要的场景中,您正在使用工具进行并行计算:您希望在显示每个图像之前应用滤镜.让我引用MDN:

关于线程安全

工人接口派生实时操作系统级线程,并铭记程序员可能会担心并发可能会导致在你的代码"有趣"的效果,如果你不小心.

但是,由于Web工作者已经与其他线程仔细控制了通信点,因此实际上很难导致并发问题.无法访问非线程安全组件或DOM.并且您必须通过序列化对象将特定数据传入和传出线程.因此,您必须非常努力地在代码中导致问题.

与实际操作系统级线程一样,除非您使用某种阻塞机制,否则不会按执行顺序进行任何假设,但这不包含在JavaScript中.因此,您需要在同一个线程中绘制操作图像.

进一步说明

顺序案例

看看下面的图片:

顺序过滤

这是techdemo中基本上发生的事情.draw()复制视频并立即过滤图像:

function draw(v,c,w,h,filter) {
    if(v.paused || v.ended) return false;
    c.drawImage(v,0,0,w,h);
    if (typeof filter === 'undefined') {
        // variable is undefined
    } else {
        var idata = c.getImageData(0,0,w,h);
        newdata = filterdata(idata,filter);
        c.putImageData(newdata,0,0);
    }
    setTimeout(draw,20,v,c,w,h,filter);
}
Run Code Online (Sandbox Code Playgroud)

如您所见drawImage,以下过滤器的调用之间没有间隙.得到的图像显示大约20毫秒.即使过滤器需要1ms,用户也可能不会注意到这一点.

平行案例

现在它变得有点复杂了.黑化文本框是直接修改画布的方法,白框表示触发事件或注册超时,黑框表示执行超时或事件处理:

平行案例

现在,会发生什么?draw仍大约每20毫秒调用一次并复制视频.然后它向工作人员发布消息.但是,在发送此消息未说明.它可以立即放置在worker的事件循环中(如图所示),也可以放在"main"的事件循环中,稍后发送(更有可能).

与顺序方法相比,此过程需要非常长的时间.请记住,您还需要发回处理过的数据,filter并且filterWorker可能会在比您原先预期更晚的时间触发事件监听器.但即使您实际处理数据并显示它,以下调用draw也会破坏您的所有辛苦工作.

要么不使用Web worker,要么使用隐藏的画布作为worker的源.