SVG入門〜サラダの国のトマト姫〜

12-5.画像

svg-saladtomato-title

昭和の良さの一つでPCゲームの面白さがあります。夢中になっていた80年代当時は、PCのグラフィックの描画速度がとても遅く、メモリ容量も貧弱でした。ゲーム画面が切り替わる度に、描画し終えるのを待たなければなりませんでしたが、それでも一つ一つのゲームが魅力に溢れ、わくわくするものばかりでした。
当時はプレイだけでなく、ゲームを作るってことにも意欲的でした。ゲームは処理速度が要だったのでアセンブラとICの制御を駆使してアセンブラプログラミングしていました。オールアセンブラってのは、本当に骨の折れる作業です。長く続けられません。作り始めても数週間で飽きてしまって、しかしまたゲームをプレイしているうちに、ゲームを作りたくなり、という連鎖でそうしてプログラミングってものにハマって、スキルアップしていったのかもしれません。

このように私の中でゲームは、プログラミングする際のモチベーションにもなるので、スキルアップ訓練に持ってこいでした。ただ、ゲーム作りで難しいのが「絵」。絵心がないので特にそう思うのですが、絵で行き詰まってしまうと、簡単にやる気が削がれてしまいます。最近の流行のゲームエンジンを使ったゲーム制作なんかは、絵が命なのでうまく描けないとすぐやる気が失せます。その点レトロゲームなら、絵も簡単に描けてしまいますので、絶好の訓練材料になります。

さて、冒頭でも述べましたが、80年代の家庭用PCのグラフィック性能はとても低く、大きな画像を格納するメモリも存在しませんでした。大きな絵を楽しむアドベンチャーゲームでは、点と点を直線でつなげて描く手法が使われることもありました。

タイトルの点と点を繋ぐ描画が終わるまで、じっと待っているわけです。全部の点がつながったら、次は塗り潰し。メモリが少ない時代に試行錯誤した先輩たちの知恵ですね。
これは一つの圧縮技術かな、と思います。当時この技術に名前がついていたかは不明ですが、紛れもなくベクター形式の画像と言えるでしょう。今回はSVGコードを書いてベクター形式の理解を深めたいと思います。

理解するに当たり、まずは手を動かして絵を描いてみます。inkscapeを使います。
inkscapeはSVG形式の画像を扱うことができるツールで、Excelの図形描画を行う感覚で使えます。

inkscapeインストール

inkscapeは、インストーラーをダウンロードして実行するか、コマンドラインからapt等でインストールする方法でインストールできます。

サイトからダウンロードしてインストール

Windowsなら、インストーラーを使うのが一番簡単です。
https://inkscape.orgからダウンロードできます。

インストーラーをダブルクリック。

インストールが始まります。

Nextをめった打ち。

Setup Typeは、いまどきディスクの容量が気になるPCを探すのが難しいので、豪華にCompleteで。

では、Installボタンをクリックしてインストール開始。

プログレスバーが走ります。

少し待ったら完了です。

ショートカットができます。クラゲみたいですね。

ショートカットをダブルクリックすると、このようなエディタが起動します。

コマンドでインストール

linuxのコマンドでインストールする場合は、apt-get等で。

~$ sudo apt-get install inkscape
~$ inkscape

起動するとLinuxでも同じようなウィンドウが表示されます。
inkscape

SVGでサラダの国のトマト姫

SVGを理解するため、inkscapeを使って、レトロゲームの「サラダの国のトマト姫」のタイトルを作って見たいと思います。

inkscapeを起動します。
saladtomato-001

ページを横向きにします。
saladtomato-002

元絵をリンクで読み込みます。ファイル名を付けておきます。
saladtomato-003

もう元絵を修正しませんので、新規レイヤーを追加して、お絵かきは新規レイヤーで行います。
saladtomato-005

矩形ツールを選択して、
saladtomato-006

枠を描きます。真っ黒になってしまうので、右クリックでフィル/ストロークを選択して、
saladtomato-008

塗りなしにします。
saladtomato-009

次はペンツールを選択して海面の線を引きます。
saladtomato-011

元絵のレイヤーを非表示にして、弾いた線を確認したら、バケツを選択し、
saladtomato-013

青色で塗ります。
saladtomato-015

他の海面の線を引いて、山を描きます。
saladtomato-020

次は、タイトルを描いて、
saladtomato-023

そのまま塗ろうとすると、海面の直線で分断されてしまうので、タイトルロゴだけ別レイヤにします。
saladtomato-024

色が濡れたら、全レイヤーを合成して、今回のタイトル絵の完成です。
saladtomato-026

重ね重ねですが「サラトマ」でも使われている点と点を結ぶ描画技術、貧弱なメモリでたくさんの画像を保存するには、ビットマップ画像ではすぐにメモリ不足に陥りますので、直線と塗りつぶしでグラフィックスを見せるって技が流行っていましたね。ラスタ画像を連想させる技術が使われていたってことに、古くても新しさを感じます。

inkscapeが生成するファイル

サラトマのタイトルを描いて、お絵かきの感触を掴んだところで、SVGの構造に目を向けたいと思います。

ファイル比較で必要な情報取得

inkscapeがどのようなファイルを生成しているか確認するため、何も描かれていないキャンバスで一旦ファイルを保存してみます。
inkscape-save

nothing.svgという名前を付けて保存しました。内容は以下の通りです。

~$ cat nothing.svg
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   width="210mm"
   height="297mm"
   id="svg2"
   version="1.1"
   inkscape:version="0.48.5 r10040"
   sodipodi:docname="新規ドキュメント 1">
  <defs
     id="defs4" />
  <sodipodi:namedview
     id="base"
     pagecolor="#ffffff"
     bordercolor="#666666"
     borderopacity="1.0"
     inkscape:pageopacity="0.0"
     inkscape:pageshadow="2"
     inkscape:zoom="0.35"
     inkscape:cx="375"
     inkscape:cy="540"
     inkscape:document-units="px"
     inkscape:current-layer="layer1"
     showgrid="false"
     inkscape:window-width="874"
     inkscape:window-height="439"
     inkscape:window-x="281"
     inkscape:window-y="204"
     inkscape:window-maximized="0" />
  <metadata
     id="metadata7">
    <rdf:RDF>
      <cc:Work
         rdf:about="">
        <dc:format>image/svg+xml</dc:format>
        <dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
        <dc:title></dc:title>
      </cc:Work>
    </rdf:RDF>
  </metadata>
  <g
     inkscape:label="レイヤー 1"
     inkscape:groupmode="layer"
     id="layer1" />
</svg>

次は、円を描いて、それを保存してみます。
inkscape-circle

上記画像をcircle.svgという名前で保存しました。

何も描かれていないファイル nothing.svgと、
円を描いたファイル circle.svgをdiffコマンドで比較してみます。

~$ diff nothing.svg circle.svg
17c17
<    sodipodi:docname="新規ドキュメント 1">
---
>    sodipodi:docname="circle.svg">
53c53,63
<      id="layer1" />
---
>      id="layer1">
>     <path
>        sodipodi:type="arc"
>        style="fill:#00ff00"
>        id="path3007"
>        sodipodi:cx="367.14285"
>        sodipodi:cy="526.64789"
>        sodipodi:rx="150"
>        sodipodi:ry="140"
>        d="m 517.14285,526.64789 a 150,140 0 1 1 -300,0 150,140 0 1 1 300,0 z" />
>   </g>
~$ 

差分を見るとよくわかります。円の描画情報だけが残りました。

円を描く単純なsvgファイルを作成

この情報を使って、円を描く単純なsvgファイルを作ってみます。

~$ cat circle.svg
<svg
   width="210mm"
   height="297mm">
    <path
       type="arc"
       style="fill:#00ff00"
       id="path3007"
       cx="367.14285"
       cy="526.64789"
       rx="150"
       ry="140"
       d="m 517.14285,526.64789 a 150,140 0 1 1 -300,0 150,140 0 1 1 300,0 z" />
</svg>
~$ 

できました。

SVGコードを書いて絵を描く

inkscapeでPNGに変換

inkscapeコマンドでPNG画像に変換もできます。

inkscape -z -e circle.png circle.svg
Background RRGGBBAA: ffffff00
Area 0:0:744.094:1052.36 exported to 744 x 1052 pixels (90 dpi)
Bitmap saved as: circle.png
~$ 

このような画像になります。
svg-circle

虹の画像を作る

では虹の画像を生成するコマンドです。円を重ねるだけです。

~$ cat <<EOL > tmp.svg 
<svg width="300" height="300">
<rect x="0" y="0" width="300" height="300" fill="white" />
<circle cx="0" cy="300" r="300" fill="red" />
<circle cx="0" cy="300" r="280" fill="orange" />
<circle cx="0" cy="300" r="260" fill="yellow" />
<circle cx="0" cy="300" r="240" fill="green" />
<circle cx="0" cy="300" r="220" fill="cyan" />
<circle cx="0" cy="300" r="200" fill="blue" />
<circle cx="0" cy="300" r="180" fill="purple" />
<circle cx="0" cy="300" r="160" fill="white" />
</svg>
EOL
inkscape -z -e tmp.png -w 300 -h 300 tmp.svg

複雑そうに見えても、意外と簡単ですよね。

svg-rainbow

SVGでテキスト画像

svg-alpha

SVGで画像にテキストを埋め込むこともできます。
SVG形式で「あ」をベクタ画像にして、inkscapeでラスタ(PNG)画像にしてみます。
スクリプトはこれです。

~$ cat text.sh
cat <<EOL > /tmp/tmp.svg
<svg width="640" height="400">
        <text x="0" y="400" font-size="400">
        あ
        </text>
</svg>
EOL
inkscape -z -e out.png /tmp/tmp.svg

以下のようにコマンドを実行すると、out.pngができます。

~$ . text.sh

svg-text-a

rotateを指定して回転、色も指定できます。

~$ cat text-laydown.sh
cat <<EOL > /tmp/tmp.svg
<svg width="640" height="400">
        <text x="0" y="0" font-size="400"
        rotate="90"
        fill="red">
        あ
        </text>
</svg>
EOL
inkscape -z -e out.png /tmp/tmp.svg

svg-text-yoko

縁取りもできます。

~$ cat text-stroke.sh
cat <<EOL > /tmp/tmp.svg
<svg width="640" height="400">
        <text x="0" y="400" font-size="400"
        stroke="green"
        stroke-width="10"
        fill="yellow">
        あ
        </text>
</svg>
EOL
inkscape -z -e out.png /tmp/tmp.svg

svg-stroke

ランダムな大きさの文字を埋め込んでみましょう。

a=""
colors="red orange yellow green cyan blue purple"
for c in $colors;do
x=`expr $RANDOM % 200`
s=`expr $RANDOM % 300`
a=$a`printf "<text x=\"%s\" y=\"200\" font-size=\"%s\" fill=\"%s\">\n" $x $s $c`
a=$a`printf "%s</text>\n" $c`
done
cat <<EOL > /tmp/tmp.svg
<svg width="640" height="300">
$a
</svg>
EOL
inkscape -z -e out.png /tmp/tmp.svg

svg-rand

SVG入門は以上になります。実際のコードを書いてみたら、以外と簡単なことがわかりました。

コメント

タイトルとURLをコピーしました