Canvasによる画像ファイル(img要素)の読み書き
Canvas要素には、img要素との間で読み書きを行う、つまりimg要素の内容をCanvasに読み込んだり、Canvasの画像をimg要素に書き出す機能があります。Canvasからの書き出しは「pngなど画像ファイルデータ形式の文字列」を介して行うため、Canvasの内容を文字列として取得する(サーバーやWebブラウザのローカルストレージに保存する)ことも可能です。
今回は、画像ファイルをimg要素に表示し、それをCanvasに転送、Canvasで簡単な画像処理を行ってまたimg要素に書き戻すテストをしてみましょう。これにより「JavaScriptで画像処理を行いその結果を出力する」流れを確認してみることにします。
まず、img要素の内容をCanvasに転送するには、CanvasコンテキストのdrawImage()を使います。drawImage()で描画位置(や描画範囲)を指定すれば、Canvasに描画が行われます。
Canvasにimgの内容が描画されれば、後はImageDataを作成して適当に書き換えましょう。
Canvasの描画内容の出力には、toDataURL()を使います。これは名前のとおりURL形式の文字列としてCanvasの画像データ(デフォルトではpng、ブラウザによってはオプション指定でjpgなど他形式での出力も可能)を取得するものです。この文字列をimg要素のsrc属性に指定してやると、その画像をimg要素に反映することができます。
さっそく、imgとCanvasの間の画像のやり取りを試してみることにしましょう。
今回は、200*200ピクセルのimg要素とCanvas要素、それにテキスト領域を用意しました。まず、img要素に適当な画像ファイルを表示し、「転送→」ボタンで隣のCanvas要素に画像を転送します。
そして、Canvas要素に読み込んだ画像を「反転」ボタンで上下反転させられるようにしました。
画像の読み込みと反転を行ったら、「URL出力」ボタンで下のテキスト領域にtoDataURL()メソッドで出力される文字列を転送し、どんな文字列になっているのか見てみましょう。最後に、「URL設定」ボタンで文字列をimg要素のsrcに設定し、画像が切り替わることを確認します。
![]() |
|
テスト用のHTMLとJavaScriptは、以下のとおりです。同じディレクトリにcanvas_image.jpgという画像ファイルが存在することを前提にしています。
<table>
<tr>
<td><img id="testImage" src="canvas_image.jpg" width="200" height="200"></td>
<td><canvas id="testCanvas" width="200" height="200" style="background: #000080;"></canvas></td>
</tr>
<tr>
<td style="text-align: center;"><button id="putImageToCanvas" onClick="putImageToCanvas()" disabled="disabled">転送→</button></td>
<td style="text-align: center;"><button id="canvasUpset" onClick="canvasUpset()" disabled="disabled">反転</button> <button id="toDataURL" onClick="toDataURL()" disabled="disabled">URL出力</button></td>
</tr>
<tr>
<td colspan="2" style="text-align: center;"><textarea id="testText" rows="6"></textarea></td>
</tr>
<tr>
<td colspan="2" style="text-align: center;"><button id="setURLtoImage" onClick="setURLtoImage()" disabled="disabled">URL設定</button></td>
</tr>
</table>
<script type="text/javascript">
var testImage = document.getElementById('testImage');
var testCanvas = document.getElementById('testCanvas');
var testContext;
var testText = document.getElementById('testText');
// CanvasとImageDataが利用可能ならボタン有効化
if (testCanvas.getContext && testCanvas.getContext('2d').createImageData) {
document.getElementById('putImageToCanvas').disabled = false;
document.getElementById('canvasUpset').disabled = false;
document.getElementById('toDataURL').disabled = false;
document.getElementById('setURLtoImage').disabled = false;
testContext = testCanvas.getContext('2d');
}
// img要素からCanvasに画像を転送
function putImageToCanvas() {
testContext.drawImage(testImage, 0, 0);
}
// 上下反転
function canvasUpset() {
var canvasImageData = testContext.getImageData(0, 0, testCanvas.width, testCanvas.height);
var canvasRGBA = canvasImageData.data;
var newImageData = testContext.createImageData(testCanvas.width, testCanvas.height);
var newRGBA = newImageData.data;
// Canvasのピクセル情報を上下反転させながらコピー
for (i = 0;i < testCanvas.height;i++) {
for (j = 0;j < testCanvas.width;j++) {
newRGBA[(j * 4) + ((testCanvas.height - 1 - i) * testCanvas.width * 4)] = canvasRGBA[(j * 4) + (i * testCanvas.width * 4)];
newRGBA[1 + (j * 4) + ((testCanvas.height - 1 - i) * testCanvas.width * 4)] = canvasRGBA[1 + (j * 4) + (i * testCanvas.width * 4)];
newRGBA[2 + (j * 4) + ((testCanvas.height - 1 - i) * testCanvas.width * 4)] = canvasRGBA[2 + (j * 4) + (i * testCanvas.width * 4)];
newRGBA[3 + (j * 4) + ((testCanvas.height - 1 - i) * testCanvas.width * 4)] = canvasRGBA[3 + (j * 4) + (i * testCanvas.width * 4)];
}
}
// コピーしたピクセル情報をCanvasに転送
testContext.putImageData(newImageData, 0, 0);
}
// Canvasの画像をURL(png文字列)化
function toDataURL() {
testText.value = testCanvas.toDataURL();
}
// URLの画像をimg要素に設定
function setURLtoImage() {
testImage.src = testText.value;
}
</script>
これで、img(画像ファイル)の画像をCanvasに設定しCanvas内でJavaScriptによる画像処理を行って、その結果を「保存やimg要素への設定が可能な文字列」として取得することができるようになりました。Webベースの画像処理アプリケーション開発に活用できそうですね。
ただし、Canvasに読み込んだ画像は、セキュリティの制約で条件(ローカルでの実行や他ドメインの画像ファイルなど)によってはImageDataの作成やURL化ができないこともあります。