C言語で画像→アスキーアートコンバータを作る
C言語での画像ファイルの取り扱いをやってみたかったので、指定した画像ファイルを自動でアスキーアートに変換して、標準出力に吐くプログラムを作ってみました。
2048と同様に、cloneしてmakeすればビルドできると思いますが、libpng,libjpegを使っているので、入ってない場合はインストールしておいてください。
$ brew install libpng
$ brew install libjpeg
Macはこれでインストールできると思います。
使うときは、変換したい画像と変換後のサイズを指定します。
$ ./png2aa hoge.png 100
こうするとhoge.pngを横幅(文字数)が100のアスキーアートに変換します。画像の縦方向の画素数を超える横幅を指定するとエラーを吐くので注意してください。
実際に使ってみるとこんな感じ。
色が付いているように見えるのは、スクショで撮ったせいです。
元画像はこれ。
変換後の方はかなり大きいように見えますが、これでもサイズは140で、ターミナルを全画面表示にしていればフォントサイズを変えなくても画面内に収まるサイズなので、以外とバカにできないんじゃないですかね?
名前がpng2aaなので、pngファイルしか無理とかそういうことではないです。
のファイル形式に対応しています。
ただ、JPEGは圧縮後のあの色ムラがかなり顕著に出てしまうのであまりおすすめしません。どうしても使いたいなら、大きい画像を小さいサイズで変換してください。
元々はPNGファイルだけでやるつもりだったんですけど、画像の入出力をライブラリ化してくれている人がいたので、これを使って他の画像形式にも対応させました。
ImageIOのソースはそんなに大きいプロジェクトではないので、全部読めば理解できると思います。
ImageIOの使い方が分かったら、次は表示文字の白黒比を求めます。
あらかじめ、こんな感じでスペース以外の全ての表示文字が入った画面をスクリーンショットしておきます。5行目の数字は横幅の確認のためです。
gist018b3c08b87e5e1948ee77ddc2bb9a50
これをmakeしたら、sortコマンドと合わせて白黒比を昇順で並べかえます。
$ make
$ ./word | sort -t , -k2
sortの区切り文字にコンマを指定しているので、出力のコンマの部分は空白にしてあるので、これをコンマに書き換えてコピペして先頭に{' ',0.000000,},を追加したもので初期化した構造体配列を用意することで、画像の白黒比に合わせてどの文字を使うかを決めています。
main.cのおおまかな処理の流れはこんな感じです。
画像読み込み
↓
グレースケールに変換
↓
画像のサイズと与えられた列数から1文字あたりの縦横の画素数を求める
↓
画像の縦横比と与えられた列数から、行数を求める
↓
1文字ずつブロックに分割して白黒比を求める
↓
最も近い白黒比を持つ文字を出力
これを繰り返して、AAに変換しています。
今後は色付き表示とか、高さ指定とかにも対応していきたいですね。