ギンの備忘録

デジタルアートやプログラミングやテクノロジー関連のこと。

【p5.js】tint()で画像のRGBチャンネルを分離する

f:id:gin_graphic:20211207220349p:plain:w400

目次


はじめに

tint()を使うことで、画像のRGBチャンネルを簡単に分離することができるので、その方法を紹介します。

tint()について

詳細について知りたい場合はp5.jsの公式Referenceをご覧ください。
ここではRGBを扱う部分に焦点を絞って説明していきます。

p5js.org

tint(指定色)によってそれ以降の描画を指定色で色味を変えて描画することができます。

まず、説明のための画像をgen_image()で作ります。
読み込んだ画像を使う場合は、それに置き換えて下さい。

function gen_image() {
  let img = createGraphics(width, height);
  img.background(0);

  let size = 300;

  img.fill(255);
  img.ellipse(width/2, height/2, size, size);

  return img;
}

gen_image()で生成する画像は下になります。

f:id:gin_graphic:20211207220229p:plain:w300

この画像に対して、tint(255, 0, 0);を適用したのが下のコードです。

function setup() {
  createCanvas(800, 450);

  let img = gen_image();

  tint(255, 0, 0);
  image(img, 0, 0);
}

tint(255, 0, 0);とすることで、元画像の赤チャネルが表示されます。

f:id:gin_graphic:20211207220234p:plain:w300

tint(0, 255, 0);とすれば緑チャネルが表示されます。

f:id:gin_graphic:20211207220238p:plain:w300

tint(0, 0, 255);とすれば青チャネルが表示されます。

f:id:gin_graphic:20211207220242p:plain:w300

tint()でRGBを分離

取り扱う画像を変更します。 gen_image()を下のようにします。

function gen_image() {
  let img = createGraphics(width, height);
  img.background(255);

  let size = 150;

  img.fill(255, 0, 0);
  img.ellipse(width/2-width/4, height/2, size, size);

  img.fill(0, 255, 0);
  img.ellipse(width/2, height/2, size, size);

  img.fill(0, 0, 255);
  img.ellipse(width/2+width/4, height/2, size, size);

  return img;
}

f:id:gin_graphic:20211207220315p:plain:w300

赤緑青の円を横に並べた画像を使ってRGBの分離を見ていきましょう。

画像をRGBチャネル毎に分離して返す関数split_rgb(img)を次のようにします。
この関数で入力画像をRGBチャネル毎に分離した3つの画像データを生成します。

入力画像に対して、tint(255, 0, 0);tint(0, 255, 0);tint(0, 0, 255);したものがRGBチャネルの抜き出しになります。

function split_rgb(img){
  let img_r = createGraphics(width, height);
  img_r.tint(255, 0, 0);
  img_r.image(img, 0, 0);

  let img_g = createGraphics(width, height);
  img_g.tint(0, 255, 0);
  img_g.image(img, 0, 0);

  let img_b = createGraphics(width, height);
  img_b.tint(0, 0, 255);
  img_b.image(img, 0, 0);

  return [img_r, img_g, img_b];
}

画像データの赤チャネルだけを表示してみましょう。
次のコードで取り扱う画像の赤色成分だけが表示されます。

function setup() {
  createCanvas(800, 450);

  let img = gen_image();
  img = split_rgb(img);

  image(img[0], 0, 0);
}

image(img[0], 0, 0);で赤チャンネルだけ表示されます。
赤だけ抜き出したことになるので、白と赤の所は赤になり、黒と青と緑の所は黒になっています。
黒と青と緑は赤い成分を含まないので、その通りですね。

f:id:gin_graphic:20211207220326p:plain:w300

image(img[1], 0, 0);とすれば緑チャネルを表示します。赤と青の所は黒になります。

f:id:gin_graphic:20211207220319p:plain:w300

image(img[2], 0, 0);とすれば青チャネルを表示します。赤と緑の所は黒になります。

f:id:gin_graphic:20211207220323p:plain:w300

これでRGBチャネルを分離して扱うことができるので、作品などに利用しやすくなりました。
tint();を使うことで簡単にRGBを分離できますね。

RGBを合成

分離したRGBチャンネルを合成する方法の紹介しておきます。

先程の赤緑青の3つの円の画像をここでも使って説明します。

次のコードで、青色だけを明るさを半分にして、合成して見ましょう。
blendMode(ADD)を使って3つの画像を加算して表示すれば、分離したRGBチャンネルを合成することができます。

function setup() {
  createCanvas(800, 450);

  let img = gen_image();
  img = split_rgb(img);

  blendMode(ADD);
  image(img[0], 0, 0);
  image(img[1], 0, 0);

  tint(128);
  image(img[2], 0, 0);
}

出力結果は下のようになります。

f:id:gin_graphic:20211207220339p:plain:w300

青色の円は明るさが半分になり、黒っぽくなりました。

背景の白だった部分は黄色になりました。
RGBでは赤と緑が混ざると黄色になります。
白から青色成分が半分減ったということは、黄色に近づくので正しく合成できていることがわかります。

まとめ

tint()を使うことでRGBチャネルを分離する処理を簡単に扱うことができます。
blendMode(ADD)を使えば、分離したものを合成することもできます。

作品の制作などに役立てば幸いです。