1

ピクセルをキャンバスにコピーし、Web ワーカーを使用してリアルタイムのビットマップ フィルターを適用するビデオを持っています。

Web ワーカーを使用すると、結果として生じる変化がキャンバスに表示されません (黒と白のはずです)。

これは私のコードです: http://www.dev.createdbychristian.com/filter-test/

中間キャンバスを使用してこれを解決できますが、実際にはそうしたくありません。

私のコードは、この例に大まかに基づいています。画像フィルター処理に Web ワーカーを使用していないだけです。 http://techslides.com/demos/html5-video-canvas.html

コードの何が問題になっていますか?

注意: Web Workers と HTML5 ビデオ / キャンバスをサポートする最新のブラウザが必要です

4

1 に答える 1

6

これはdraw()、 が WebWorker の戻り値を待たずに を使用するために発生しますrequestAnimationFrame。継続的にフィルター処理された画像が必要な場合はdraw、フィルターが適用された後に呼び出す必要があります。

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

ただし、フィルターに時間がかかる場合はdraw、キャンバスが色付きのデータで塗りつぶされて、変更に気付くのが早い可能性が非常に高くなります (現在のバージョンで FF17 の白黒バージョンを見ることができました)。

コードの何が問題になっていますか?

操作の順序が重要なシナリオで並列計算の機能を使用しています。つまり、画像が表示されるにフィルターを適用したいとします。MDN を引用させてください:

スレッドセーフについて

Workerインターフェースは、実際の OS レベルのスレッドを生成します。気をつけていないプログラマーは、注意しないと同時実行がコードに「興味深い」影響を与える可能性があることを懸念するかもしれません。

ただし、Web ワーカーは他のスレッドとの通信ポイントを慎重に制御しているため、実際には並行性の問題を引き起こすことは非常に困難です。スレッドセーフでないコンポーネントや DOM にはアクセスできません。また、シリアル化されたオブジェクトを介して特定のデータをスレッドに出し入れする必要があります。したがって、コードで問題を引き起こすには、非常に懸命に取り組む必要があります。

また、実際の OS レベルのスレッドの場合と同様に、なんらかのブロック メカニズムを使用しない限り、実行順序を仮定することはできませんが、これは 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);
}

ご覧drawImageのとおり、次のフィルターの呼び出しの間にギャップはありません。結果の画像は、約 20 ミリ秒間表示されます。フィルターに 1 ミリ秒かかる場合でも、ユーザーはこれに気付かない可能性があります。

パラレルケース

ここで、もう少し複雑になります。黒く塗りつぶされたテキスト ボックスは、キャンバスを直接変更するメソッドです。白いボックスは、トリガーされたイベントまたは登録されたタイムアウトを示し、黒いボックスは、タイムアウトの実行またはイベントの処理を示します。

パラレルケース

さて、どうなるでしょうか?draw約 20 ミリ秒ごとに呼び出され、ビデオをコピーします。次に、ワーカーにメッセージを投稿します。ただし、このメッセージがいつ送信されるかは明記されていません。ワーカーのイベント ループにすぐに配置することも (図に示すように)、「メイン」のイベント ループに配置して後でディスパッチすることもできます (可能性が高い)。

このプロセスは、シーケンシャルな方法と比較して非常に長い時間がかかります。処理されたデータも送り返す必要があること、および と の両方filterfilterWorkerイベント リスナが最初に予想したよりも後でトリガーされる可能性があることに注意してください。しかし、実際にデータを処理して表示したとしても、次の への呼び出しにより、drawすべての苦労が台無しになります。

解決

Web ワーカーを使用しないか、非表示のキャンバスをワーカーのソースとして使用してください。

于 2012-11-30T09:23:41.130 に答える