今回も前回と同様にテキストから画像を作成します。前回は白黒のビットマップ画像でしたが、今回はグレースケール(灰色の画像)とフルカラー画像を作成します。今回も前回同様にUNIX系が基本ですが改行コード等に注意すればWindows 10でも作成できます。
グレースケール画像を生成
PGMはグレースケール画像を扱う形式です。 まず、8段階のグレースケール画像を作成します。画像のサイズは8×1ドット、最大輝度の段階は8です。
PGMもPBMと同様に最初に画像形式、情報を示すヘッダーを書きます。最初の一行にはP2の文字を指定します。これがPGM形式である事を示す文字列になります。マジックナンバーの次の行には画像の横幅と縦幅を指定します。横幅と縦幅の間には半角空白を入れます。PGMの場合、横幅と縦幅の次にグレースケールの最大輝度を指定します。輝度の値は0から始まります(0が完全な黒色)。今回は最大輝度が8段階、つまり0〜7なので7を指定します。
その次の行からグレースケールの値を数値で記述していきます。PBMと違いピクセルデータとピクセルデータの間には空白や改行が必要です。 以下のようにすると8×1ドットのグラデーション画像になります。
P2
8 1
7
0 1 2 3 4 5 6 7
前回同様に無理矢理コマンドラインから作成してみましょう。面倒だなと思う人はテキストエディタで作成しても構いません。が、無理矢理コマンドを使う連載なので、やはりコマンドラインから作成してもらえるとよいのではないかと思います。
今回も作成するディレクトリはデスクトップとします。cdコマンドでカレントディレクトリをデスクトップにしておきます。こうしておくと画像ファイルが生成された事がすぐにわかります。
cd ~/Desktop
次に前回同様にechoコマンドとリダイレクトを使って作成します。
echo 'P2'>gray.pgm
echo '8 1'>>gray.pgm
echo '7'>>gray.pgm
echo '0 1 2 3 4 5 6 7'>>gray.pgm
macOSだと正しく画像ファイルが作成されるとアイコンで確認できます。画像をアプリケーションで開いて確認します。
横1ドットの灰色のグラデーションになっているはずです。もし、なっていなかったら、どこか入力ミスしている可能性があります。確認してみてください。
コマンドから少し手軽に入力
echoコマンドの練習をするのも面倒になってきた人もいるかもしれません。もう少し簡単に入力したいところです。
そんな時にはcatを使いましょう。今度はcatを使ってグラデーション画像ファイルを作成します。
以下のように入力すると、コンソールから入力した文字をgay2.pgmファイルとして保存できます。
cat >gray2.pgm
上記のようにコマンドを入力します。これで文字を入力できる状態になります。
あとは画像フォーマットにしたがって画像データを入力していきます。今度は8×2ピクセルのグレー画像です。
P2
8 2
7
0 1 2 3 4 5 6 7
7 6 5 4 3 2 1 0
最後まで入力したらctrl (control) キーを押したままdキーを押します。すると入力した内容がファイルに保存されます。catコマンドもしくはアプリケーションで確認してみましょう。
もし、どこかで間違えて入力してしまった場合は、テキストエディタで修正しましょう。もちろん練習のために再度入力し直しても構いません。
先ほどは最初から画像データを入力しましたが、ヘッダー部分は同じで画像のピクセルデータだけが異なる場合もあります。そのような場合、先ほどと同様にヘッダーから入力すると面倒です。 そんな場合は、あらかじめヘッダーファイルを用意しておき、画像のピクセルデータだけ入力するようにします。
まず、ヘッダーファイルを用意します。ここではhead.txtファイルで以下の内容にしました。echoコマンドで作成してもcatコマンドで作成してもエディタを使って作成しても構いません。
P2
4 4
7
それではヘッダーファイルの後にピクセルデータを入力します。以下のようにコマンドを入力します。head.txtの後の-は標準入出力を示します。つまり以下のような指定をするとhead.txtの後にキーボードから入力した文字を連結してgray3.pgmに出力することになります。
cat head.txt - >gray3.pgm
4×4=16なので16ピクセル分のデータを入力します。データ入力後はctrl (control) キーとdキーを押せばコマンドラインに戻ります。
0 0 1 1
2 2 3 3
4 4 5 5
6 6 7 7
入力が終わったら確認しましょう。期待通りの結果になっていなければ、もう一度やり直しましょう。
グレースケールのランダムノイズ画像を生成
前回は白黒のノイズ画像を作成しましたので、今回も同様にグレースケールでのノイズ画像を生成してみましょう。作成する画像サイズは前回と同じ256×256とします。
基本的には前回と同じ方法で作成することができます。PGMは最大輝度を指定できるので$RANDOMでの最大値である32767を指定すると簡単に生成できます。コマンドラインから以下のように入力するとグレースケールのランダムノイズ画像を生成できます。
echo 'P2'>noise.pgm
echo '256 256'>> noise.pgm
echo '32767'>> noise.pgm
for i in {1..65536};do echo -n "$RANDOM ";done>> noise.pgm
アプリケーションで確認してみましょう。
画像処理アプリケーションの定番であるPhotoshopではうまく表示されないようです。多分256段階までしか処理されないのかもしれません(画像は16ビットとして処理はされているようですが)。 そこで以下のように256段階のグレースケールノイズとして処理するようにします。
echo 'P2'>noise2.pgm
echo '256 256'>> noise2.pgm
echo '255'>> noise2.pgm
for i in {1..65536};do echo -n "$(($RANDOM % 256)) ";done>> noise2.pgm
Photoshopで確認すると今度は期待通りの表示になります。
グラデーション画像を生成
グレースケールノイズを生成するスクリプトを少し変更(応用)するとグラデーションを描くことができます。
まず以下のようにすると左から右へ明るくなっていくグラデーションになります。forを使って縦方向と横方向に繰り返し処理を行っています。横方向の変数の値をechoを使って出力します。
echo 'P2'>grad.pgm
echo '256 256'>> grad.pgm
echo '255'>> grad.pgm
for i in {0..255};do for j in {0..255};do echo -n "$j ";done;done>> grad.pgm
逆に左から右に向かって暗くなるグラデーションは以下のようになります。echoで255から変数jの値を減算した結果を出力します。bash,zshでは変数や数値で四則演算などを行うことができます。+-*/記号が加減乗除に該当します。
echo 'P2'>grad.pgm
echo '256 256'>> grad.pgm
echo '255'>> grad.pgm
for i in {0..255};do for j in {0..255};do echo -n "$((255-$j)) ";done;done>> grad.pgm
縦方向のグラデーションにする場合は以下のようになります。変数を変更しただけです。これは上から下に向かって明るくなっていきます。
echo 'P2'>grad.pgm
echo '256 256'>> grad.pgm
echo '255'>> grad.pgm
for i in {0..255};do for j in {0..255};do echo -n "$i ";done;done>> grad.pgm
上から下に向かって暗くなるグラデーションの場合は以下のようになります。横方向と同様に255から変数の値を減算します。
echo 'P2'>grad.pgm
echo '256 256'>> grad.pgm
echo '255'>> grad.pgm
for i in {0..255};do for j in {0..255};do echo -n "$((255-$i)) ";done;done>> grad.pgm
変数同士で計算させると以下のようなグラデーションも生成できます。32768段階のグラデーションの場合は以下のようになります。ただ、この方法で作成したPGMファイルはPhotoshopでは正常に表示されません。
echo 'P2'>grad.pgm
echo '256 256'>> grad.pgm
echo '32767'>> grad.pgm
for i in {0..255};do for j in {0..255};do echo -n "$((($i*$j)/2)) ";done;done>> grad.pgm
Photoshopでも表示できるようにするには以下のように256段階に値を収めるようにします。計算式を変えれば面白い画像を描くことができます。色々チャレンジして見ると面白いでしょう。
あと、最大輝度の値を変えると表示される結果が変わり、Photoshopのレベル補正と似たような効果を得ることができます。
echo 'P2'>grad.pgm
echo '256 256'>> grad.pgm
echo '255'>> grad.pgm
for i in {0..255};do for j in {0..255};do echo -n "$((($i*$j)/256)) ";done;done>> grad.pgm