JavaScript入門[HTML5編]グレースケール,セピア調化

  1. HOME
  2. JavaScript入門[HTML5編]
  3. グレースケール,セピア調化

このページではcanvas内の図形をピクセル毎に操作して、 グレースケールやセピア調に変換する方法を見ていきます。

ピクセル操作の方法

まず最初に、ピクセル操作に関連した命令を見ておきましょう。

imagedata = context.getImageData( x , y , w , h )
座標(x,y)から幅(w),高さ(h)の範囲の図形の情報を、左辺のimagedataに格納します。
左辺のimagedataを「ImageDataオブジェクト」と呼びます。
context.putImageData( imagedata , x , y )
座標(x,y)を左上端として、imagedataの情報がcanvasに描画されます。

つまり、getImageData()を使ってcanvasに描画された図形等のピクセル情報を取得し、 それを操作して、putImageData()で再描画していきます。

ImageDataオブジェクトからは、以下のデータを取得できます。

imagedata.width
イメージの横幅を取得します。
imagedata.height
イメージの縦幅を取得します。
imagedata.data
イメージのピクセル情報を格納した配列を取得します。

このimagedata.dataで取得できるピクセル情報は、配列の形式になっています。 赤,緑,青,透過率の4つの連続した要素で1ピクセルの情報を表します。 つまり100×100ピクセルの画像では、配列の要素数はピクセル数の4倍の40,000になります。 全ての要素は0~255の整数値で構成されています。

グレースケールにする

では実際に画像をグレースケール化するスクリプトを見てみましょう。 スクリプトの下にカラー画像を描画しています。 画像の表示方法は、画像を描画するのページで確認なさってください。 ボタンを押すと、そのカラー写真がグレースケールに変換されるようにしてみます。

赤・緑・青のピクセルデータをグレースケール化するための計算式は、 画像処理におけるアルゴリズムのページを参考にして製作しました。 小数値で計算すると処理が重くなるので、 整数値で計算するように変更しています。 導き出された値もparseInt()で切り捨てを行い、整数値にしています。

<canvas id="cv1" width="360" height="240"></canvas>

<form>
<input type="button" value="グレースケール" onclick="img_gray()">
</form>

<script>
function img_gray()
{
  var ctx = document.getElementById("cv1").getContext("2d");
  var imagedata = ctx.getImageData(0,0,360,240);
  var idata = imagedata.data;  //ピクセルデータをidataにセット

  var num = idata.length;  //ピクセルデータ総数を取得
  var pix = num / 4;       //ピクセル数を取得

  for ( var i = 0 ; i < pix ; i++ )
  {
    //赤・緑・青のデータを取得(今回透過率は変更しません)。
    var r = idata[ i*4 ];
    var g = idata[ i*4 + 1 ];
    var b = idata[ i*4 + 2 ];

    //グレースケール化する処理
    var g = parseInt(( r*30 + g*59 + b*11 ) / 100);

    //グレースケール化したデータを再セット
    idata[ i*4 ] = g;
    idata[ i*4 + 1 ] = g;
    idata[ i*4 + 2 ] = g;
  }
  ctx.putImageData(imagedata,0,0); //変更したピクセルデータを書き出す
}
</script>

<描画結果>canvasタグにはCSSで二重線の枠を付けています

セピア調にする

グレースケールに少し手を加えるだけでセピア調にすることも可能です。 上のスクリプトのうち、グレースケール化する計算をした後、 データを再セットする時に以下のようにします。 なおセピア調化するための計算式も、 画像処理におけるアルゴリズムを参考にさせてもらいました。

//グレースケール化する処理
var g = parseInt(( r*30 + g*59 + b*11 ) / 100);

//セピア調にするデータを再セット
idata[ i*4 ] = parseInt( (g/255)*240 );
idata[ i*4 + 1 ] = parseInt( (g/255)*200 );
idata[ i*4 + 2 ] = parseInt( (g/255)*145 );

<描画結果>canvasタグにはCSSで二重線の枠を付けています

このようにcanvasを使うと、JavaScriptからピクセルデータを扱うことができます。 他にネガポジ反転なども簡単に行うことができるでしょう。