画像

2019-05-20

本章のあらすじ

  • Processingと画像
  • ぱらぱらまんがを作る
  • 画像から色を採取する
作例:画像を細分化して各々ずらす

画像

これまで描いてきたスケッチは、単純な図形を組み合わせた抽象的なものが中心でした。画像を絵作りに取り入れることで、その画像の持つ質感や複雑さを取り込み、スケッチにまた別の趣を持たせることができます。絵画やイラストが得意な人は、その武器を存分に活かすことができるようになります。

Processingで画像を描く

画像を用意する

まずはじめに空のスケッチを保存し、コード .pde と同じ場所に data フォルダーを作ります。

スケッチに使いたい画像( .jpg, .png など)が用意できたら、 data フォルダーに入れましょう。好きな画像を用意してもよいですし、なければモナ・リザをお借りしましょうか。

モナ・リザ

画像を読み込む

読み込んだ画像データを保持するために、新たな変数の型 PImage が登場します。

// 画像を保持する変数 img を宣言
PImage img;

data フォルダーに配置した画像を読み込むには loadImage() を使います。ファイル名は文字列で指定するので、ダブルクォート "" で囲います。

void setup() {
  // data フォルダーにある monalisa.jpg を読み込み、変数 img に代入
  img = loadImage("monalisa.jpg");
}

読み込んだ画像を描画する

読み込んだ画像を表示するのが image() です。

image( 画像 , X座標 , Y座標 );

コードの全体像はこんな感じになります。

PImage img;

void setup() {
  size(600, 600);
  background(255);
  
  // data フォルダーにある monalisa.jpg を読み込み、変数 img に代入
  img = loadImage("monalisa.jpg");
  // 読み込んだ画像を描く
  image(img, 0, 0);
}

正しく表示されたでしょうか?

実行時にエラーが出るときは

実行時に The file "~" is missing … のエラーが出るときは…エラーメッセージとの接しかたを思い出しつつ、落ち着いて原因を探っていきましょう。

メッセージが言っているのは、「ファイルが見つからないかアクセスできない」ということです。この状況でのよくあるミスは…

  • data フォルダーのスペルが違う( date とか dete とか)
  • ファイル名や拡張子が違う( pngjpg を間違えているとか)
  • そもそもファイルを入れていない(別のスケッチの data フォルダーに入れてしまっているとか)

再確認してみましょう。

練習:ハンコを作ってみる

クリックしたらその位置に画像が描かれる、ハンコのようなものを作ってみましょう。

ヒント

  • クリックしたときに実行されるのは mousePressed() ブロック
  • 画像は image( 画像 , X座標 , Y座標 ) で指定した位置に描ける
  • クリック位置は mouseX, mouseY で取得できる

(→stamp

発展

  • mouseDragged() にするとどう変化する?
  • クリックした位置が画像の左上端ではなく、中心になるように描けるだろうか?
  • マウスの右ボタンを押したときに異なる画像をスタンプできるだろうか?(mouseButton
  • mousePressed()mouseDragged() で描く画像を変えるなどしておもしろい効果は出せないだろうか?

その他の活用例

Processingでは、他にも画像を題材とした活用法がたくさんあります。いくつかスケッチを作ってみましょう。

ぱらぱらまんが

ぱらぱらまんがの要領でイラストを動かしてみましょう。同じ大きさのイラスト画像を複数枚用意してください。

用意できたらスケッチを描いていきましょう。まずは描いたフレーム画像をすべて読み込んで変数に入れておきます。

// コマ画像
PImage img0;
PImage img1;
PImage img2;
PImage img3;

void setup() {
  size(600, 600);

  // コマ画像をすべて読み込む
  img0 = loadImage("frame0.png");
  img1 = loadImage("frame1.png");
  img2 = loadImage("frame2.png");
  img3 = loadImage("frame3.png");
}

そして、「いま何フレーム目を表示しているか」を保持しておく必要があるので、int 型の変数をひとつ宣言しておきましょう。

// 何フレーム目を表示するかのカウンター
int count;

void setup() {
  

  // カウントの初期値を 0 にする
  count = 0;
}

これで準備が整ったので、あとはカウントを増やしていく処理と戻す処理、カウントに応じて画像を描き分ける処理を書けば完成です。 (→flipbook

void draw() {
  background(255);

  // カウントを増やしていく(末尾まで達したら 0 に戻す)
  count = count + 1;
  if (count >= 4) {
    count = 0;
  }

  // カウントに応じて画像を出し分ける
  if (count == 0) {
    image(img0, 245, 245);
  }
  else if (count == 1) {
    image(img1, 245, 245);
  }
  else if (count == 2) {
    image(img2, 245, 245);
  }
  else if (count == 3) {
    image(img3, 245, 245);
  }
}

実行すると…。

速い!ちょっと速すぎですね。 draw() ブロックは調子がよいときは1秒間に60回ほど実行されてしまうので、コマ送りのアニメーションには速すぎるようです。

カウンターを float 型にして、もっとゆっくり増加するようにしてみましょう。 (→flipbook_slower

// 何フレーム目を表示するかのカウンター
// (速度調整のため小数にする)
float count;

void draw() {
  background(255);

  // カウントを少しずつ増やしていく(末尾まで達したら 0 に戻す)
  count = count + 0.1;
  if (count >= 4) {
    count = 0;
  }

  // カウントを floor() で切り捨てしてフレーム番号を計算
  int f = floor(count);

  // フレーム番号に応じて画像を出し分ける
  if (f == 0) {
    image(img0, 245, 245);
  }
  else if (f == 1) {
    image(img1, 245, 245);
  }
  else if (f == 2) {
    image(img2, 245, 245);
  }
  else if (f == 3) {
    image(img3, 245, 245);
  }
}

floor() は初出ですが、 float 型の小数を切り捨てて int 型に変換してくれるものです。

いい感じに落ち着きましたね。

さて、これを応用すると、例えばマウスの位置に応じて画像を出し分けることもできます。カーソルのほうを向いてくれるキャラクターなど、いろいろ考えられそうですね。 (→flipbook_cursor

void draw() {
  

  if (mouseX < 200) {
    // カーソルが左のほうにあるとき:
    // 左向きの画像を描画
    image(img1, 245, 245);
  }
  else if (mouseX > 400) {
    // カーソルが右のほうにあるとき:
    // 右向きの画像を描画
    image(img3, 245, 245);
  }
  else {
    // それ以外のとき:
    // 正面向きの画像を描画
    image(img0, 245, 245);
  }

  
}

画像から色を採取する

画像の変数.get( X座標 , Y座標 ) を使うと、画像の好きな点から色を採取できます。採取した色は color 型の変数に入れられ、そのまま fill()stroke() に指定できます。 (→image_pen

// 画像用の変数
PImage img;

void setup() {
  size(600, 600);
  background(255);
  noStroke();

  // 画像を読み込む
  img = loadImage("monalisa.jpg");
}

void mouseDragged() {
  // 画像のカーソル位置の色を取得してcolor型の変数に入れる
  color col = img.get(mouseX, mouseY);
  // 採取した色を塗りに設定
  fill(col);

  // カーソル位置に円を描く
  ellipse(mouseX, mouseY, 100, 100);
}

void draw() {
}

関連:キャンバスから色を採取する

先ほどの例は画像の色を採取するものでしたが、いま描いているキャンバスの色を取得する方法もあります。

画像の色の取得方法と似ていますが、 get( X座標 , Y座標 ) を使うと現在のキャンバスの色を採取できます。これを利用すれば、例えばクリックした位置から色を塗り広げるような効果を作り出せます。 (→image_pen_canvas

void mouseDragged() {
  // キャンバスから色を採取して塗りに設定
  color col = get(mouseX, mouseY);
  fill(col);

  
}

本章のまとめ

  • 画像は loadImage() で読み込む
  • 読み込んだ画像は PImage
  • 画像を使うと、その質感や複雑さをスケッチに取り入れられる

その他、ここでは扱わないがよく使う機能

  • 画像の一部分をコピー: copy()
  • 画像に着色・不透明度を変更: tint()