このページの本文へ

HTML5のcanvasで作る画像フィルター (4/6)

2009年10月07日 10時00分更新

文●古籏一浩

  • この記事をはてなブックマークに追加
本文印刷

Safari/Google Chrome編:
getImageData()/putImageData()でまとめて処理

 レンダリングエンジン「WebKit」を利用している「Safari」「Google Chrome」には、Friefox同様、getImageData()/putImageData()が用意されています。本来であればサンプル3のプログラムがそのまま動くはずです。

 ところが実際には、サンプル3のプログラムはSafari/Google Chromeでは動作しません。どうやらピクセル単位の読み書きの処理を繰り返すとうまく動作しないようです。そこで、Safari/Google Chromeでは、繰り返し処理の前にすべてのキャンバスのピクセルデータをgetImageData()で取得しておきます。取得したピクセル情報はdata配列に入っていますので、参照する位置を順番に変えていきフィルター処理をかけます。

 フィルター処理が完了したらputImageData()を使って、処理済みの画像データを一括で描画します。この方法はFirefoxでも利用でき、毎回ピクセル値を読み出さないため、処理は高速です。

 実際のプログラムはサンプル4です。Safari/Google ChromeでもFirefox同様、あらかじめ画像を読み込んでいないと画像が表示されませんので、imgタグで読み込ませています(Google Chromeでは読み込みタイミングのためか、画像が表示されず真っ黒になることがあります)。

fig4.png

Safariで赤色フィルター処理が行われた画像が表示される


●サンプル4(Safari 4/Google Chrome 2以降専用)

【HTML】


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="ja">
    <head>
        <meta http-equiv="content-type" content="text/html;charset=utf-8">
        <title>Sample</title>
        <link rel="stylesheet" href="css/main.css" type="text/css" media="all">
        <script type="text/javascript" src="js/sample.js"></script>
    </head>
    <body>
        <h1>ブラウザーでフィルター処理</h1>
        <canvas id="myCanvas" width="300" height="169">canvasに対応したブラウザーで実行してください</canvas>
    </body>
</html>


【sample.js】


window.onload = function(){
    var _canvasW = 300;   // 横幅300ピクセル
    var _canvasH = 169;   // 縦幅169ピクセル
    var canvas = document.getElementById("myCanvas");
    var context = canvas.getContext("2d");
    var imgObj = new Image(_canvasW, _canvasH);
    imgObj.src = "http://■■■■/●●●●/asama.jpg";
    context.drawImage(imgObj, 0, 0);
    var imageData = context.getImageData(0, 0, _canvasW, _canvasH);   // ピクセル値を取得する
    var w = imageData.width;
    var h = imageData.height;
    var pixelImage = context.createImageData(w, h);
    // フィルター処理
    for(var y=0; y<h; y++){
        for(var x=0; x<w; x++){
            var ptr = (y * w + x ) * 4;   // ピクセル処理する配列の要素位置を計算
            var R = imageData.data[ptr + 0];
            var G = imageData.data[ptr + 1];
            var B = imageData.data[ptr + 2];
            R = R  * 2;
            if (R > 255) R = 255;
            G = Math.floor(G / 2);
            B = Math.floor(B / 2);
            pixelImage.data[ptr + 0] = R;
            pixelImage.data[ptr + 1] = G;
            pixelImage.data[ptr + 2] = B;
            pixelImage.data[ptr + 3] = 255;
        }
    }
    context.putImageData(pixelImage, 0, 0);
}

■■■■:ドメイン
●●●●:ディレクトリパス

この連載の記事

一覧へ

この記事の編集者は以下の記事をオススメしています