putImageDataによるCanvasの画像データ設定

スクリプトで描画されたグラフィックを保持するHTML5のCanvas要素には、描画内容(Canvasのビットマップ、ピクセルデータ)を配列で直接操作するフレームバッファ機能があります。このフレームバッファは、ImageDataオブジェクトの形で取得、設定が可能で、ImageDataオブジェクトのdataプロパティにある配列に数値を設定してCanvasコンテキストのputImageData()に渡すと、その数値データでWebページ上のCanvasに描画を行うことが出来ます。

数値の配列であれば、JavaScriptからでも高速に処理できるので、プログラムでピクセル毎に画像処理を行ったり描画内容を計算で作り出すようなWebアプリ開発では威力を発揮しそうですね。
まずは、JavaScriptで書き込んだ配列をCanvasに表示してみることにしましょう。

ImageDataのdataプロパティにあるピクセルデータには、Canvas内の各ピクセルの色情報が赤、緑、青、アルファ(不透明度)の順に0-255の数値として格納されています。1ピクセルが4つの要素になるわけですね。そして、この1ピクセル4つの要素を一まとまりとして、左から右へ横一列のピクセル列が上から下へと並べられています。

つまり、横幅widthピクセルのImageDataにおいて、(x, y)のピクセルはdataプロパティ(配列)の

x * 4 + y * width * 4

の位置からの4つの要素に格納されているわけです。
具体的には

data[x * 4 + y * width * 4]が(x, y)の赤成分
data[1 + x * 4 + y * width * 4]が(x, y)の緑成分
data[2 + x * 4 + y * width * 4]が(x, y)の青成分
data[3 + x * 4 + y * width * 4]が(x, y)の不透明度

となります。

ImageDataオブジェクトは、CanvasコンテキストのcreateImageData()メソッドで大きさを指定して作ることが出来ます。たとえば、Canvas要素の参照cvから32*32ピクセルのImageDataを作るなら

cv.getContext('2d').createImageData(32, 32)

といった形になります。

こうして作成したImageDataのdataプロパティにピクセルの色情報を設定したら、CanvasコンテキストのputImageData()メソッドで描画先の座標を指定すると、その位置に設定内容を描画することが出来ます。

とりあえず、実際の流れを確認するために32*32ピクセルのCanvas要素test1から32*32ピクセルのImageDataを作って適当にピクセルデータを設定し、Canvas全体、つまり描画位置(0, 0)で描いてみましょうか。こんな感じになります。

<canvas id="test1" width="32" height="32"></canvas>

<script type="text/javascript">

	var cv = document.getElementById('test1');

	// Canvas要素とImageDataが実装されていれば処理続行
	if (cv.getContext && cv.getContext('2d').createImageData) {

		// Canvasのコンテキスト取得
		var context = cv.getContext('2d');

		// ImageDataオブジェクト作成
		var imgData = context.createImageData(32, 32);

		// 各ピクセルの色情報設定
		for (i = 0;i < 32;i++) {
			for (j = 0;j < 32;j++) {

				// 赤成分
				imgData.data[j * 4 + i * imgData.width * 4] = j * 8;

				// 緑成分
				imgData.data[1 + j * 4 + i * imgData.width * 4] = 255 - (i * 8);

				// 青成分
				imgData.data[2 + j * 4 + i * imgData.width * 4] = i * 8;

				// アルファ成分
				imgData.data[3 + j * 4 + i * imgData.width * 4] = 255;

			}
		}

		// CanvasのコンテキストにImageDataを設定
		context.putImageData(imgData, 0, 0);

	}

</script>

表示結果(Canvas要素やImageDataが未実装のWebブラウザでは表示されません)。

Canvas要素対応Webブラウザで実際にグラデーション表示を確認したら、ループ内の色成分設定を色々書き換えて色成分やピクセルの並び順を確認してみてください。

以上で「JavaScriptで作成した数値データ(フレームバッファ)をImageDataとしてCanvasに描く」流れを確認できました。フレームバッファを活用すれば、「プログラムによる計算」で描けるものなら何でも描けるようになる(もちろん処理速度の問題はありますが)ので、Webアプリケーション開発の可能性が一気に広がりそうです。


創作プログラミングの街