[69-11] canvasでビットマップを操作しよう(ビットマップの明度や色調の変更)

canvasはビットマップ画像のピクセル情報を数値として扱えます。
それによって、例えばカラーの画像をグレーにしたり...など、いろんなことができます。
画像を2つ用意せずに、カラー画像をグレースケールに変化させたりできるんですよ。使えますね♪

それをやるにはまず「ImageData」の概念を理解して、ImageDataの中の「data」の構造を知る必要がありました。順番に見ていきましょう。

本日のINDEX
  1. ImageDataのメソッド(createImageData, getImageData, putImageData)
  2. 各ピクセル情報の取り出し方(Canvas Pixel Array)
    1. data の構造
    2. canvasの幅と高さが必要な場合の x,y を使った dataの取り出し方
    3. lengthプロパティを使った dataの取り出し方
  3. canvasに createImageData でグラデーションを描く
  4. canvas上のグラフィックの一部を変更する
  5. canvasに描画した写真をグレースケールにする
  6. img要素の画像をcanvasにゲットしてセピア調にする

今回のサンプルはこちらです。

サンプル1
canvasに createImageData でグラデーションを描く。

サンプル2
canvas上のグラフィックの一部を変更する。

サンプル3
canvasに描画した写真をグレースケールにする。

サンプル4
img要素の画像をcanvasにゲットしてセピア調にする。

ImageDataのメソッド
 (createImageData, getImageData, putImageData)

canvasでピクセルデータをいじるために ImageData というオブジェクトがあります。
ImageData はビットマップ。ピクセルの集合体なんです。
ImageData には以下のメソッドが用意されています。

  • createImageData(width, height) 幅と高さのあるImageDataを作る
  • createImageData(imagedata) ImageDataと同じサイズのImageDataを作る
  • getImageData(x, y, width, height) canvas上のモノをImageDataにする
  • putImageData(imagedata, x, y) ImageDataをcanvasに書き出す

createImageData は、何もネタが無いところでImageDataを作るためのもの。最初は高さと幅だけがある透明なImageDataができます。これを編集して、createImageData(imagedata) に渡すと別編集ができるというわけ。

getImageData は、今canvasにあるグラフィックをゲット(get)します。
x,y で左上の始点を、width, height で幅と高さを指定してゲット。それを編集するわけです。

createImageDatagetImageData で取り込んだ ImageData は、各ピクセルデータを編集できるようになっています。詳細はこのあと説明します。

で、編集し終わった ImageData は、まだ宙に浮いた状態ってかんじ。この時点ではブラウザ上で見えません。
そこで putImageData でcanvasに戻して(put)やる必要があるんです。

putImageDataは、詳しくは下記のような引数を持っていて、dirtyX以降の引数は省略可能です。
putImageData(imagedata, x, y, dirtyX, dirtyY, dirtyWidth, dirtyHeight)
引数 imagedataは編集し終わった ImageData、x,y はcanvas上の描き出しの始点です。
dirtyX, dirtyY は ImageData上での切り出す始点、dirtyWidth, dirtyHeight はその始点からの幅と高さです。作った ImageDataをトリミングできるんですね。
(でもなんでダーティなんですかね? 汚れ役?まさか...。闇の中にいるイメージでしょうか?)

各ピクセル情報の取り出し方(Canvas Pixel Array)

create か get した ImageData は、3つのプロパティを使うことで、いろいろ操作できます。

  • width ImageData の幅
  • height ImageData の高さ
  • data ImageData の各ピクセルのrgba。このすぐあと↓詳細。

● data の構造

ImageData はビットマップ。なので各ピクセルが集まって画像を作っているのですが、
この「data」は1ピクセルごとにさらに細かく「rgba」の4つの情報に分かれています。
rgba とはご存知の、赤・緑・青・透明度(アルファ)の情報で 0〜255の256段階で表現されます。
(ってことは、canvas の ImageData は256階調ってことですね)
data は1つ1つのピクセルの rgba情報 というわけです。

data はこの rgba の情報を 4つ一組で「配列」として持っているので javaScript で編集できるという画期的なものなんだそうです。
この配列のことを「canvas Pixel Array」って言うそうですよ。

data について図解するとこんなかんじ。
1個1個のピクセルを、左上から始まって最後の右下のピクセルまで、下図のようにダ〜ッと読むんだそうです。

画像の1個1個のピクセルの中のrgba情報を data(ImageData.data)と呼ぶということね。
dataの幅は width(ImageData.width)、高さは height(ImageData.height)と呼びます。

さて、いよいよ各ピクセルデータを取り出す方法です。
r(赤の情報)なら r だけを取り出すことができてはじめていろんな加工ができるわけですから、これができなきゃ話になんない。

● canvasの幅と高さが必要な場合の x,y を使った dataの取り出し方

ImageData を「canvas のサイズに合わせてグラデーションにしたい」など、幅や高さが必要な場合は、x,y座標を使います。
計算式に納得するために、4×3ピクセルのサイズの画像で考えてみました。
まずは下の図を見てください。
各ピクセルは、x0,y0 〜 x3,y2 まであります。
ピンクのピクセル(x2,y1)に注目して、このピクセルがスタートから何番目にいるか考えてみます。

今いる座標の横位置は簡単ですね。x座標のままでOK。
今いる行より前(上)のピクセル数は、自分の y座標 × width(幅)で出すことができます。ですので、それを足せばOK。
x + y * width
ピンクのピクセルに当てはめてみると、
2 + 1 * 4 = 6 アタリですね。
(1からでなく0からカウントしますよ。配列だし。)

そして、各ピクセルに rgba4つの情報があるので、上の式に単純に4をかけます。
(x + y * width) * 4
これが各ピクセルの先頭の「r」の情報です。
例のピンクのピクセルに当てはめてみると、
(2 + 1 * 4) * 4 = 24 合ってますね。

x,y座標は、すべてのピクセルの座標を当てはめることができるのですから、
この式で、すべてのピクセルの「r」の情報をピックアップできるというわけです。

で、g、b、a は1つずつずれて配置されているわけですから、
r が、(x + y * width) * 4 なら、
g は、(x + y * width) * 4 + 1
b は、(x + y * width) * 4 + 2
a は、(x + y * width) * 4 + 3 で取り出せるというわけです。

この x,y座標を使う方法は、今回のサンプル1で使っています。
実際には下記のように for文を使ってrgbaをピックアップします。(詳細はサンプルで)

var imgd = imageData.data;
  for (var y = 0; y < height; ++y) { /*yが0から高さの数まで1ずつ増えるあいだで*/
    for (var x = 0; x < width; ++x) { /*xが0から幅の数まで1ずつ増えるあいだに*/
    var base = (x+y*width)*4; /*ImageDataのrgbaのうちrをゲットしといて*/
    imgd[base+0] = /*ここに r の情報の操作を書きます*/ ;
    imgd[base+1] = /*ここに g の情報の操作を書きます*/ ;
    imgd[base+2] = /*ここに b の情報の操作を書きます*/ ;
    imgd[base+3] = /*ここに a の情報の操作を書きます*/ ;
    }
  }

● lengthプロパティを使った dataの取り出し方

こっちのほうが使用頻度高いかも。(今回のサンプルでは、サンプル1 以外全部これを使ってます)

javaScriptのプロパティの length は、その名のとおり文字列の長さ(というか情報の総数)をゲットできます。
そうやってゲットした「data」の総数を4で割ったら「r」の情報というわけです。

実際には下記のように for文を使ってrgbaをピックアップします。(詳細はサンプルで)
r をピックアップしたら、後の gba は1ずつ足してピクアップできるというのは x,y 座標の考え方と同じです。

	var imgd = imageData.data;
    var len = imgd.length/4;
    for (var i = 0; i < len; ++i) {
        imgd[i*4] = /*ここに r の情報の操作を書きます*/ ;
        imgd[i*4+1] = /*ここに g の情報の操作を書きます*/ ;
        imgd[i*4+2] = /*ここに b の情報の操作を書きます*/ ;
        imgd[i*4+3] = /*ここに a の情報の操作を書きます*/ ;
    }

では、以上を踏まえて、実際に「data」を操作してみましょう。

canvasに createImageData でグラデーションを描く

サンプル1 は、canvasに createImageData でグラデーションを描いています。

このカンバスは width="600" height="220" です。
r(red)は横方向に0 〜 255 まで増して行くようにしています。600ピクセルを256段階になるように設定します。
g(green)は縦方向に0 〜 255 まで増加。220ピクセルを256段階になるように設定します。
b(blue)は左上から斜め方向にに255 〜 0 にしています。これは256になった時点で終わります。
a(alpha value 透明度)はマックスの 255 にしています。

このグラデーション、CSSのグラデと違ってかなり複雑なことができるので、サイトの背景などに使えそうです。

canvas上のグラフィックの一部を変更する

サンプル2 は、canvas上にまず赤い四角形を描画。
その真ん中を getImageData でゲットして、a(alpha value 透明度)だけ半調にして putImageData で canvasに戻しています。

これは写真を使ったら、おもしろい表現ができそうですね。

canvasに描画した写真をグレースケールにする

サンプル3 は、グレースケールを試してみました。
まず canvas上に写真を描画。(写真の描画は「[69-4] canvasに画像を描画しよう」に詳細)
それを getImageData でゲットして、グレースケールにしてから putImageData で隣りの canvasに戻しています。

1つのカラー画像を用意するだけ、グレースケールの画像は不要なので、フォトギャラリーなどに利用すると便利ですね。

img要素の画像をcanvasにゲットしてセピア調にする

サンプル4 は、グレースケールの応用で、セピア調にしています。

このサンプルでは img要素から画像を canvasに取り込んでいます。
それを drawImage で canvasに描画。これをさらに getImageData でゲットして、セピア調にしてから putImageData で canvasに戻しています。

このサンプルは、ロールオーバーで元のカラー画像が現れるようにしていますが、これはCSSによる演出です。
CSSで img要素の上に canvas要素が乗っかるようにし、ロールオーバーで canvas要素の透明度が 0 になるようにしています。

フォトギャラリーを作る(外部参考サイト)

canvasを使ったフォトギャラリーで、参考になるサイトを見つけました。
2012年の記事で、ちょっと古いですが、十分勉強になりました。

PEHAA BLOG
「Create your portfolio gallery
using html5 canvas – tutorial」

こちらは、HTML上にcanvas要素は書かず、javaScriptでcanvas要素を imageの前に書き出すようにしています。
たくさんの写真のソースもシンプルにできています。
ソースの詳しい説明も載っていますよ。

次回予告

いかがでしたか? やっと canvasっておもしろい!って思えるところまで来た感があります。
最初のころの四角とか線とか描いてたときは、けっこうつまんなかったですね(笑)

次回は、canvasをサイトの背景に使ってみます。
これは今回よりハマりました。おもしろいですし、デザイナーなら必須かも。
私はコレがやりたくて、canvas の勉強を始めたと言っても過言ではありません(笑!)

関連記事
この記事をはてなブックマークに追加

やる気を保つためにランキングに参加しています。
応援してくださると すっごいやる気を出します! (笑)

初心者にも使いやすい(と思う)レンタルサーバー

最近よく「レンタルサーバーはどこがいい?」とご質問が来ます。
自分でも使っていてオススメなのはミニバード。管理画面がわかりやすくていい感じす。
仕事で使ってるロリポップもわかりやすい管理画面で、初めてでもすんなり使えると思います。
両方とも、なんといっても料金が安いです。初めてだとなるべく安いほうがイイですからね。

それよりちょっと料金は高いけど、高スペックでコスパが良く、信頼性も高いサーバといえば、やはりさくらのレンタルサーバと、XSERVER(エックスサーバー)だと思う。この2つは老舗でユーザーも多いので、質問する場がたくさんあり、初心者の方でもイケるだろうと思います。

レンタルサーバーは、たくさんあり過ぎて迷いますよね。近いうちに、初心者にも良さげなサーバーについて記事にまとめます。*記事をアップしたらココにもリンクを貼ります。

スポンサーリンク

コメントの投稿

スポンサーリンク
最新記事
Category
オススメの本
Links
Calendar
07 | 2017/08 | 09
- - 1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31 - -
Archive
RSS Link
Profile

yuki★hata

Author : yuki★hata
せめて月1回の更新をめざします~。

メールフォームはこちら

スポンサーリンク
スポンサーリンク
Copyright © ほんっとにはじめてのHTML5とCSS3 All Rights Reserved.