見出し画像

#PCD2020 で使った、文字から何かを描画するテクニック

タイトル絵にあるような、Processing Community Day Tokyo 2020 関連ツイートで使った「文字を元に何かを描画する」テクニックを紹介します。

テクニックというよりも、力技、ベタな方法ですので読んでズッコケないでね。

画像1

このテクニックで何が出来るのか

このテクニックは一言で言うと「文字を構成する点の座標をいかに得るか」です。
点の座標が得られればそれを使って、
・その点に色を付ける
・点のところを四角や円にする
・点を動かす

などいろんなことが出来るようになります。

例えばこんな風に。
・点に色を付ける

画像5

・点のところを四角や円にする

画像6

・点を動かす


画像2

考え方とコード例

文字を点の集合と考えて、文字を形作る点の座標を取得する。その方法はこんな風に考えました。

1.黒字で白い方眼紙上に文字を書く。
2.方眼紙のマス目を一個ずつ見ていく。
3.マス目が黒ければそこは文字を形作る点と判断。
4.点と判断したマス目の座標を書き出していく。

なんてベタ! だがそれがイイ!👍

コードは p5.js で説明します。こちらがその点々の座標を p5.Vector の配列として返す関数です。

/* text2vs : 元の文字から、その文字を構成する点の座標(vector)の配列を返す
* _text    : 元の文字
* _size    : 文字を描画するサイズ
* _density : 文字を構成する点を取得する割合。1.0 なら全部取得、0.1 なら 10% 取得。取得はランダムなので均一になるとは限らないし、正確にその割合で取得するわけでもない。
* _width   : 文字を描画するキャンバスサイズの幅
* _height  : 文字を描画するキャンバスサイズの高さ
*
* pixelDensity 無視
*/
function text2vs(_text, _size, _density, _width, _height) {
 pg = createGraphics(_width, _height)
 pg.background(255);
 pg.noStroke();
 pg.fill(0);
 pg.textSize(_size);
 pg.textAlign(CENTER, CENTER);
 pg.text(_text, _width * 0.5, _height * 0.5);
 pg.loadPixels();

 const vectors = new Array();
 for (let w = 0; w < _width; w++) {
   for (let h = 0; h < _height; h++) {
     let pIndex = (_width * h + w) * 4;
     // brightness は RGB の最大値になるそうなので
     if (max(pg.pixels[pIndex], max(pg.pixels[pIndex + 1], pg.pixels[pIndex + 2])) < 50) {
       if (random(1.0) < _density) {
         vectors.push(createVector(w, h));
       }
     }
   }
 }

 return vectors;
}

pg が方眼紙で、そこに _text を黒色で書き、方眼紙をひとマスずつ pixels[] で参照しながら明度が 50以下だったら黒と判断し、座標を p5.Vector の形式で vectors という配列に入れていくという仕組みです。

pg は createGraphics(_width, _height) で生成した仮想的な画面と言えばよいでしょうか。

 pg.background(255);

などのように pg. と付けることで、その仮想画面上に描画していきます。
仮想画面上への描画は実際の画面には何も描画されません。

 pg.loadPixels();

とすることで、pg 上に描画した結果の全ピクセル情報が pixels[] に入ります。これは p5.js のお約束です。詳しくはマニュアルを見てね。

注意が必要なのは pixels[] の扱いです。
描画結果の 1ピクセルに対して、pixels[] はそのピクセルの Red、Green、Blue、Alpha の 4つ値が入るので、配列のインデックスを計算するために

     let pIndex = (_width * h + w) * 4;

このような計算が必要になります。

さらに、Retinaディスプレイなど画面密度が異なる画面に対応するためには pixelDensity() も考慮する必要があります。
詳しくはマニュアルをどうぞ。

今回は pixelDensity() はガン無視してしまいました。ごめんなさい。

画像3

応用例

応用例としてこの方法で所得した座標を元にベクター・フィールドを描画してみます。

画像7

全体のコードはこちらにありますのでよろしければどうぞ。


同じコードでパラメータを変えることでこのような文字ならざるものを描くこともできます。(描きたいかは別として)

画像8


絵文字でこんな遊びも!(遊んでみたいかは…)


ベクター・フィールド以外でも下記のような考え方が使えると思います。
ぜひ遊んでみてください。

点と点を線で結ぶ
沢山の作例を紹介くださっている おかずさんの記事です。

点からニョキニョキ生えてくる

ランダム・ウォーク


画像4

余談:このテクニックを使った PCD 関連ツイート例

昨年の PCD では開催前日に「24時間で 24作品ツイートしたら面白かろう」と突発的に思いつき、実際やってはみたもののとても大変でした。

当日はゆっくり PCD のストリーミングを見て楽しみたいなと思い、今回は PCD の日程発表のあった 2020/01/12 から開催に向けて毎日作品をツイートしていきました。
その一部を作例として紹介します。

点と点を線で結ぶ

点からニョキニョキ生えてくる

ランダム・ウォーク

塗る

点の部分に立体を描く

モーフィング


もし、他の作例にもご興味ありましたら私の Twitter をご覧いただければと思います。
ついでにフォローもしてね。😘


Processing Community Day Tokyo 2020 ストリーミング視聴しての感想もよろしければご覧ください。





この記事が面白かったらサポートしていただけませんか? ぜんざい好きな私に、ぜんざいをお腹いっぱい食べさせてほしい。あなたのことを想いながら食べるから、ぜんざいサポートお願いね 💕