複数のワーカーを生成して並列に処理する
最近のコンピューターは2コアや4コアなど複数のCPUを搭載しています。せっかく複数のCPUを搭載しているのですから、Web Workersを同時に複数動作させることでCPUパワーを余すことなく利用できそうです。現実的にはワーカーの処理方法はブラウザーによって異なるので、必ずしも期待どおりの結果は得られませんが(ブラウザーごとの結果の違いは最後に紹介します)、複数のワーカーを生成して並列に処理させてみましょう。
サンプル7はワーカー1つにつき256回呼び出し、ワーカー内で赤、緑、青の輝度のピクセル数を調べていました。今度はワーカー内では与えられた輝度と指定されたチャンネル(RGB/赤緑青)だけの結果を返すようにします。
ワーカーを呼び出す側ではR/G/Bそれぞれに対応した3つのワーカーを生成し、調べたい輝度とチャンネル(実際は配列のオフセット)を指定します。これでまとめて3つのワーカーが動作することになります。
実際のプログラムはサンプル8です。実行すると3つのワーカーが同時に処理され、ヒストグラムが順次表示されていきます。
●サンプル8[HTML]
<!DOCTYPE html>
<head>
<meta charset="utf-8" />
<title>画像分析(複数のワーカーを利用)</title>
</head>
<body>
<h1>画像分析(複数のワーカーを利用)</h1>
<canvas id="myCanvas" style="width:300px;height:150px;border:1px solid black">
Canvasに対応したブラウザーでご覧下さい。
</canvas>
<form action="./image.cgi" method="get">
<input type="button" id="checkStart" value="分析開始" />
</form>
<div id="result"></div>
<script>
document.getElementById("checkStart").addEventListener("click", function(){
document.getElementById("result").innerHTML = "分析中...<br>";
var brightness = 0; // チェックする輝度
var red = "";
var green = "";
var blue = "";
// ワーカー設定
var myWorker = new Worker("analysis.js");
myWorker.addEventListener("message", function(event){
red += '<img src="r.gif" width="1" height="'+(event.data.red/8)+'">';
green += '<img src="g.gif" width="1" height="'+(event.data.green/8)+'">';
blue += '<img src="b.gif" width="1" height="'+(event.data.blue/8)+'">';
document.getElementById("result").innerHTML = red+green+blue;
brightness++;
if (brightness < 256) {
startWorker();
}
}, true);
var img = context.getImageData(0, 0, canvasW, canvasH).data;
function startWorker(){
myWorker.postMessage({
width: canvasW,
height: canvasH,
brightness: brightness,
imageData: img
});
}
startWorker();
}, true);
var canvasObj = document.getElementById("myCanvas");
var context = canvasObj.getContext("2d");
var canvasW = canvasObj.width;
var canvasH = canvasObj.height;
var imgObj = new Image();
imgObj.src = "sunflower.jpg";
imgObj.onload = function(){
context.drawImage(imgObj,0,0,300,150);
}
</script>
</body>
</html>
●サンプル8[analysis.js]
addEventListener("message", analysis, false);
function analysis(event){
var count = 0;
var pixels = event.data.imageData;
var ofst = event.data.offset; // 読み出すチャンネルのオフセット
var c = event.data.brightness; // 輝度
for(var y=0; y<event.data.height; y++){
for(var x=0; x<event.data.width; x++){
var ptr = (y * event.data.width + x) * 4;
var n = pixels[ptr + ofst];
if (n == c) { count++; }
}
}
postMessage(count);
}