Linux のヒント: コマンドラインからピクセル定規を作成する

Bash スクリプト、シェルの算術演算、ImageMagick を使って画像上に線を引いたり、テキストを追加したりする

Linux® のコマンドラインと基本的な Bash スクリプトの手法、そして ImageMagick を使って画像上に線を引いたり、テキストを追加したりする方法を学びましょう。またそれを学ぶ中で、ピクセル定規を作成しましょう。

Ian Shields, Senior Programmer, IBM

Ian ShieldsIan Shields は、developerWorks Linux ゾーンの様々な Linux プロジェクトに関わっています。彼はノースキャロライナ州 Research Triangle Park にある IBM のシニア・プログラマーです。1973年にオーストラリアのキャンベラでシステム・エンジニアとして IBM に入社して以来、カナダのモントリオールやノースキャロライナ州 Research Triangle Park で、コミュニケーション・システムやパーベイシブ・コンピューティングに携わってきました。彼はいくつかの特許を保持しています。Australian National University にて純粋数学および哲学で学位を取得し、また North Carolina State University にてコンピューター・サイエンスで修士号と博士号を取得しています。Ian について詳しく知るには、My developerWorks で彼のプロフィールを見てください。


developerWorks 貢献著者レベル

2009年 7月 23日

私は時々、画像やブランクのキャンバス上に線を引いたり、テキストを追加したりしなければならないことがあります。私はつい最近、developerWorks の記事の中にピクセル定規のシンプルな画像を含める必要がありました。画像の幅は 572 ピクセルでなければなりません。これは developerWorks の記事の画像として現在推奨されている最大値に合わせるためです (この推奨値は「Illustrating your article or tutorial for developerWorks」に書かれている値です)。画面上で使用するピクセル定規は Linux 用にも Windows 用にもさまざまなものがあります (「参考文献」を参照) が、私に必要だったのは GIF か JPEG か PNG の単純な画像でした。このヒントでは、Bash スクリプト、シェルの算術演算、そして ImageMagick を使ってピクセル定規を作成する方法を説明します。

キャンバスを作成する

どんな芸術家であっても、最初に必要なものはキャンバスです。そこで、ImageMagick の XC という疑似画像タイプを使ってキャンバスを作成しましょう。キャンバスが用意できたら、色も必要になります。色としては、ImageMagick に多数用意された名前付きの色のなかから 1 色を選ぶこともでき、あるいはカスタムの色を使うこともできます (ImageMagick のドキュメントへのリンクは「参考文献」を参照してください。そこには疑似画像のタイプと色の名前がすべてリストアップされています)。リスト 1 は明るい青の 572x100 のキャンバスを convert コマンドを使って作成する方法を示しています (convert コマンドは通常、異なる画像フォーマットに変換する場合や、画像を変更する場合に使われます)。

リスト 1. キャンバスを作成する
convert -size 572x100 xc:lightblue ruler1.gif

図 1 は新しいキャンバスを示しています。

図 1. 明るい青の 572x100 ピクセルのキャンバス (ピクセル定規用)
明るい青の 572x100 ピクセルのキャンバス (ピクセル定規用)

線を何本か追加する

キャンバスが作成できたので、ピクセル定規上の位置を示す目盛りを描画しましょう。Web ベースのグラフィックスでは、インチ当たりのピクセル数は 72 ppi (pixels per inch) が標準的なので、最初の目盛りを 72 ピクセル目の位置に配置し、キャンバス画像の下端から 30 ピクセルの高さの目盛りになるようにします。そのためには、線の両端を指定し、その 2 点間を結ぶ黒く塗りつぶした直線を描画するコマンドを入力します。

リスト 2. キャンバスに 1 本の線を追加する
convert  -fill black -draw "line 72,70 72,100" ruler1.gif ruler2.gif

図 2 は 1 本の線が描画された新しい画像を示しています。

図 2. キャンバスの左端から 72 ピクセル目に 1 本の縦線を描画する
キャンバスの左端から 72 ピクセル目に 1 本の縦線を描画する

これと同じことをピクセル定規上に必要なそれぞれの目盛りに対して行っても面白くありません。そこで、seq コマンドを使用して横方向に 72 ピクセル離れたオフセットのリストを生成し、for ループを使ってピクセル定規上に主要な目盛りを描画することにします (リスト 3)。

リスト 3. キャンバスの 72 ピクセルごとに縦線を追加する
convert  -fill black -draw "$(for n in $(seq 0 72 572) ;\
 do echo line $n,70 $n,100 ; done)" ruler1.gif ruler3.gif

ここで、2 つのコマンド置換を使ってそれぞれの縦線の仕様を生成し、描画操作を行っていることに注目してください。また、左端の 0 にも目盛りを配置します。図 3 を見ると、定規らしくなっています。

図 3. キャンバスの左端から 72 ピクセルごとに縦線を描画する
キャンバスの左端から 72 ピクセルごとに縦線を描画する

さらに線を描画するためのスクリプト

この段階になるとコマンドラインが少し複雑になりますが、定規にはまだ主な目盛りしかありません。そこで、スクリプトの登場です。リスト 4 ではシェルの算術演算と for ループを使用して、既に配置してある目盛りの中間に 20 ピクセルの高さの目盛りを配置するとともに、これまで配置した目盛り同士の間の 6 ピクセルごとに 10 ピクセルの高さの目盛りを配置しています。このスクリプトに buildruler.sh という名前を付けて、この記事のための作業ディレクトリーの中に置きます。

リスト 4. すべての目盛りを定規に追加する
#!/bin/bash
# Take user parameters or set defaults
rulername="$1"
rulerlength="$2"
rulername="${rulername:=ruler.gif}"
rulerlength="${rulerlength:=572}"
drawstring=""
#Build the line definitions for the ruler marks
for x1 in `seq 0 72 $rulerlength`; do
  drawstring="$drawstring line $x1,70 $x1,100"
  for x2 in 0 36; do
    (( offset = $x1 + $x2 ))
    drawstring="$drawstring line $offset,80 $offset,100"
    for x3 in `seq 6 6 30`; do
      (( offset2 = $offset + $x3 ))
      drawstring="$drawstring line $offset2,90 $offset2,100"
    done
  done
done
#Create the ruler
convert -size "${rulerlength}x100" xc:lightblue -fill black \
 -draw "$drawstring" "$rulername"

注意する点として、ユーザーが定規の名前を変更できるように、また定規の長さを指定できるように、2 つのパラメーターを追加しています。これで、ピクセル定規は図 4 のようになります。この定規の生成には ./buildruler.sh ruler4.gif というコマンドを使っています。

図 4. すべての目盛りが 6 ピクセルずつ離れて定規上に配置された状態
すべての目盛りが 6 ピクセルずつ離れて定規上に配置された状態

テキストを追加する

引用符の扱い

スクリプトを作成する際に面倒なことの 1 つとして、引用符が必要な場合と不必要な場合、そして引用符で囲まれたストリングをパラメーターとして渡すための方法を考えなければなりません。この記事で紹介するスクリプトに引用符がどのように使われているか、特に注意してください。

今度は定規上の長い目盛りに数字でラベルを付けましょう (0、72、144 など)。ImageMagick に対して、使用するフォント、そしてそのフォントのサイズと色を指示する必要があります。もちろん、0 はピクセル定規の左端でなければなりませんが、72 ピクセル目の位置に 2 桁や 3 桁の数字を配置するとアンバランスに見えます。それを修正するために、数字を少し左にシフトし、目盛りを中心とした中央揃えに見えるようにします。この内容を追加したスクリプトをリスト 5 に示します。

リスト 5. ピクセル定規にラベルを追加する
#!/bin/bash
# Take user parameters or set defaults
rulername="$1"
rulerlength="$2"
rulername="${rulername:=ruler.gif}"
rulerlength="${rulerlength:=572}"
drawstring=""
#Build the line definitions for the ruler marks
for x1 in `seq 0 72 $rulerlength`; do
  drawstring="$drawstring line $x1,70 $x1,100"
  for x2 in 0 36; do
    (( offset = $x1 + $x2 ))
    drawstring="$drawstring line $offset,80 $offset,100"
    for x3 in `seq 6 6 30`; do
      (( offset2 = $offset + $x3 ))
      drawstring="$drawstring line $offset2,90 $offset2,100"
    done
  done
done
#Add the labels
labelfont="-fill black -font helvetica -pointsize 24  -draw"
labelstring="text 0,60 \"0\" "
for x1 in 72; do
  (( offset = $x1 - 12 ))
  labelstring="$labelstring text $offset,60 \"$x1\" "
done
for x1 in `seq 144 72 $rulerlength`; do
  (( offset = $x1 - 18 ))
  labelstring="$labelstring text $offset,60 \"$x1\" "
done

#Create the ruler
convert -size "${rulerlength}x100" xc:lightblue -fill black \
 -draw "$drawstring" $labelfont "$labelstring" "$rulername"

すると定規は図 5 のようになります。

図 5. ラベルとすべての目盛りが付けられたピクセル定規
ラベルとすべての目盛りが付けられたピクセル定規

テキストを配置する

では、どの程度テキストをずらすのか、あるいは、どの程度目盛りから離して配置するのかを、どのように判断したのでしょう。その簡単な答えは、実験と推測の結果ということになりますが、これは理想的なソリューションではありません。

より適切にテキストを配置するためには、そのテキストを含む長方形のボックスの大きさを知る必要があります。しかしそれは、どのようなフォントなのか、そのフォントがプロポーショナル・フォントかどうか、その他容易に計算できない要素に依存します。幸いなことに、ImageMagick を使ってキャンバスを作成する方法と同じ方法で、ラベルも作成することができます。ここでは Pixel Ruler というタイトルを作成し、このタイトルを 36 ポイントのフォントにします。このラベルは画像として作成され、ここではラベルのサイズを identify コマンドを使って判断します (リスト 6)。

リスト 6. タイトルを作成し、そのサイズを測定する
$ convert -fill NavyBlue -background Lavender -font helvetica -pointsize 36 \
 label:"Pixel Ruler" label.gif
$ identify "label.gif"
label.gif GIF 175x36 175x36+0+0 8-bit PseudoClass 256c 1.98kb

ここではこのテキストをネイビー・ブルーにし、背景色としてラベンダー色を追加し、ページの背景から文字が目立って見えるようにしています。ただし得られる画像のサイズは背景色があってもなくても同じです。この結果としてのラベルの画像を図 6 に示します。

図 6. 画像としてのラベル
画像としてのラベル

ファイルを作成するよりも良い方法として、ImageMagick の INFO クラスを使用すると、例えばベースラインがどこにあるかなど、テキストに関して、さらに詳しい情報を知ることができます。ここでは十分に大きなキャンバス上にテキストを作成してから、ちょうどそのテキストが収まるサイズのボックスだけが残るようにボックス周辺のキャンバス部分を削除します (リスト 7)。

リスト 7. INFO 画像クラスを使ってフォント情報を判断する
$ convert -size 572x100 xc:lightblue -font helvetica -pointsize 36 \
  -fill black -undercolor lavender  -annotate +40+50 'Pixel Ruler' -trim info:
xc:lightblue XC 174x36 572x100+40+23 16-bit DirectClass

注釈付きテキストの開始点の y 座標はテキストのベースラインを表現します。上記の出力から、このテキストが 174x36 ピクセルのサイズのボックスに収まることがわかります。このサイズと先ほどの結果との間の 1 ピクセルの相違は重要ではありません。このボックスの上端は元のキャンバスの上端から 23 ピクセル下に配置されています。ベースラインは元のキャンバスの上端から 50 ピクセル下だったので、これはベースラインが実際にはテキストの上端から 27 ピクセル (50 マイナス 23) 下にあり、ディセンダー (訳注: ディセンダーとは、gjpqy などの文字のためにベースラインより下に突き出した部分) は 9 ピクセルであるということです。図 7 はこの関係を、ボックス周辺が削除されていないキャンバス上に配置された画像を使って示しています。

図 7. ラベルのメトリクス
ラベルのメトリクス

これでラベルの寸法がわかったので、ベースラインを画像の上端から 40 ピクセル下に配置し、ラベルを横方向に中央揃えします。最終的なスクリプトをリスト 8 に示します。このスクリプトは記事からダウンロードすることもできます。

リスト 8. 最終的なスクリプト
#!/bin/bash
# Take user parameters or set defaults
rulername="$1"
rulerlength="$2"
rulername="${rulername:=ruler.gif}"
rulerlength="${rulerlength:=572}"
drawstring=""
#Build the line definitions for the ruler marks
for x1 in `seq 0 72 $rulerlength`; do
  drawstring="$drawstring line $x1,70 $x1,100"
  for x2 in 0 36; do
    (( offset = $x1 + $x2 ))
    drawstring="$drawstring line $offset,80 $offset,100"
    for x3 in `seq 6 6 30`; do
      (( offset2 = $offset + $x3 ))
      drawstring="$drawstring line $offset2,90 $offset2,100"
    done
  done
done
#Add the labels
labelfont="-fill black -font helvetica -pointsize 24  -draw"
labelstring="text 0,60 '0' "
for x3 in 72; do
  offset3=$(($x3 - 12 ))
  labelstring="$labelstring text $offset3,60 '$x3' "
done
for x4 in `seq 144 72 $rulerlength`; do
  offset4=$(( $x4 - 18 ))
  labelstring="$labelstring text $offset4,60 '$x4' "
done
#Add a title
titledimension=$(convert -size 572x100 xc:lightblue -font helvetica \
  -pointsize 36  -fill black -undercolor lavender\
  -annotate +40+50 'Pixel Ruler' -trim info: | awk ' {print $3 } ')
titlewidth=${titledimension%x*}
titlefont="-fill NavyBlue -font helvetica -pointsize 36"  
titlepos=$(( (($rulerlength - $titlewidth)) / 2 ))
titletext="text $titlepos,30 'Pixel Ruler' "
#Create the ruler
convert -size "${rulerlength}x100" xc:lightblue \
 -fill black  -draw "$drawstring" $labelfont "$labelstring" \
 $titlefont -draw "$titletext" "$rulername"

最終的なピクセル定規を図 8 に示します。

図 8. タイトルが付いた最終的なピクセル定規
タイトルが付いた最終的なピクセル定規

芸術的なセンスがない者の作品としては悪くありません。


現実に近い例

画像がインデントされている場合には (例えばリストの中にある場合など)、それに応じて developerWorks で許容される最大幅も小さくなります。そうした場合、記事と共に提出する画像を以下の便利な定規でチェックすることができます。

  • これは番号なしリストの中で使うための短い定規です。この定規は ./buildruler.sh ruler9.gif 400 というコマンドを使って作成しました。
    図 9. 400 ピクセルの定規
    400 ピクセルの定規
    • そしてこれは、もっと短く、さらにインデントされた定規です。この定規は ./buildruler.sh ruler10.gif 300 というコマンドを使って作成しました。
      図 10. 300 ピクセルの定規
      300 ピクセルの定規

まとめ

この簡単な演習では ImageMagick を使って、線とテキストを含む画像をスクリプト化するための基本的な手法をいくつか学びました。これら以外の手法も、developerWorks の記事、「コマンドラインからのグラフィックス操作」と「コマンドラインからのグラフィックス操作 第2回」に説明されています。また ImageMagick のホームページにも他の例が数多く紹介されています。リンクは「参考文献」を参照してください。

ここで紹介したスクリプトは完璧ではありません。例えば、長さを表す数字が定規として意味のある十分に大きな正の数字かどうか、あるいは指定されたファイルが ImageMagick において有効な画像ファイル・タイプかどうか、などを検証していません。こうした点以外にも問題は見つかるはずです。例えば、定規のラベルが上記の図 10 のように欠けるかもしれませんが、このスクリプトではこうした点を考慮してありません。

また、好きなだけ多くの要素をパラメーター化することもできます。例えば色や定規の高さをパラメーターとして追加してみてください。

このヒントでは Linux での ImageMagick の使い方に焦点を絞りましたが、ImageMagick は Windows など他のプラットフォームでも利用することができます。ここで紹介した手法を、皆さんのお好みのプラットフォーム上でお気に入りのスクリプト・ツールを使って試してみてください。


ダウンロード

内容ファイル名サイズ
Script to build your own pixel rulerbuildruler.zip1KB

参考文献

学ぶために

製品や技術を入手するために

  • さまざまなオペレーティング・システム用に、いくつかの画面定規があります。
  • developerWorks から直接ダウンロードできる IBM ソフトウェアの試用版を利用して皆さんの次期 Linux 開発プロジェクトを構築してください。

議論するために

  • My developerWorks community に参加してください。個人プロファイルとカスタムのホームページを利用することで、皆さんの関心事項に合わせて developerWorks を調整することができ、また他の developerWorks ユーザーとやり取りすることができます。

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Linux
ArticleID=422844
ArticleTitle=Linux のヒント: コマンドラインからピクセル定規を作成する
publish-date=07232009