たった15KBで、スケーラブルかつ写実的なバラク・オバマ

僕は開発者ではなく、普段はほぼ完全に手描きで制作している[イラストレーター](http://shajitsu.com/)です。
SVG というファイル形式と自分の得意とするモノクロペン画はかなり親和性が高いんじゃないかと以前から感じていまして、その移植についての実験を [SVG Advent Calendar 2016](
http://www.adventar.org/calendars/1428) の25日目の記事として投稿してみます。

#動機、経緯#

アナログなペン画イラストレーションをピュアなSVGファイルとして描き換えたいと思った。

以前、[自働トレース変換プログラムでペン画ビットマップ画像をSVGに変換してみたこと](https://twitter.com/Tsait0/status/759048308828483585)はあったけども、１本の線の輪郭を無理やり「パス」として処理してしまうので、出来上がったファイルは元画像と比較してファイルサイズがコンパクトにはならなかった。
ほとんど同じ見た目とファイルサイズで、でもスケーラブルになった、という感じ。

今回は人力で、純粋に「ストローク」のみで線を表現する最適化されたSVGファイルとして描き直した場合、どのくらいサイズが軽くなるかを試してみた。

#完成作品#

![201612_002-Merge_paths.svg.gz](https://s3-ap-northeast-1.amazonaws.com/tksh/201612_002-Merge_paths.svg.gz)

https://s3-ap-northeast-1.amazonaws.com/tksh/201612_002-Merge_paths.svg.gz 


#作業工程#

##元となるアナログペン画の制作とデータ化##

まずは普通にアナログ絵を[描く](https://www.youtube.com/playlist?list=PL-QfMOoq_vxMqGR9nu4TiP0SgiBb4zjHM)。

![201612_001-flatten-2048px.png](https://qiita-image-store.s3.amazonaws.com/0/85140/9879266b-fc6e-01d2-283f-37ea9d2c9682.png)

画材: A4サイズのケント紙にペンとインクとマーカー（POSCA）
元にした写真: [Obama Honors Dempsey](http://www.defense.gov/Media/Photo-Gallery?igphoto=2001294796)

完成したアナログペン画を下絵にするためにスキャニングする。
原画原寸（A4, 210x297mm）で 1200dpi の解像度で、モノクロ2値で。

##Inkscapeでペンタブレットを使ってなぞる##

デフォルトファイル形式がSVGであるベクターグラフィックソフト「Inkscape」で新規ドキュメントを作り、スキャンした画像を配置する。

「不透明度」を30%などにして淡いグレーで表示し、それをガイドに上から100%の黒色の「鉛筆ツール」でなぞる。

機材: Wacom ペンタブレット Sサイズ Bamboo Fun CTH-470

##線の太さの調整##

一番細い線が 1pt 、とかだとキリが良いかな思って、それに合うようにドキュメントとスキャン画像をA3サイズに拡大して描き始める。

アナログ画材で描く時の線幅は、力の入れ具合や紙に接する角度よって微妙な大小が生じる。
その線幅の大小を忠実に再現するのではなく、ざっくりと幾つかの値にまとめてしまえば、出来上がるSVGファイルも軽くて圧縮が効きやすいようになるのではと考え、一番細い線から順に

1pt, 2pt, 3pt, 5pt, 8pt, 13pt 

という６つのフィボナッチ級数でやってみようとしばらく描き進める。

が、少し描き進めていくうちに、より繊細なニュアンス表現をするためにやっぱり 1pt よりも細い線幅が欲しくなってしまう。
しかも 1pt, 2pt, 3pt, という前半の増え方が、ちゃんとした写実表現をするためには粗過ぎるな、とも感じる。

なので、線の太さを６つから７つに増やし、隣り合った数の比率もなるべく同じになるように調整し、

0.6pt, 1pt, 1.7pt, 3pt, 5pt, 8pt, 13pt

と定めて、なぞる作業を再開。

##線は直線のみで##

データを出来るだけ小さくしたかったので、曲線を使わずに、全て直線のみで描く。

直線なら、４つの値で一本の線が描ける。
始点の X座標、Y座標 と終点の X座標、Y座標 で合計４つ。

曲線だと、それに加えて、始点と終点のそれぞれから出る「ハンドル」の座標が必要なので、直線の倍の合計８つの値が必要。

##ツールで最適化##

描き終えたら、Inkscape で保存したSVGファイルを「[SVGOMG](https://jakearchibald.github.io/svgomg/)」という、SVG最適化ツール「[SVGO](https://github.com/svg/svgo)」のwebアプリ版を使って最適化する。

SVGOMG: https://jakearchibald.github.io/svgomg/

「Prefer viewBox to width/height」 の項目はオフにしておかないと出来上がったファイルが Chromium 系ブラウザ上で拡大縮小できない。

SVGOMGからダウンロードしたままでのファイルサイズは 37.1 KB。

##手で最適化##

SVGOMG で最適化しても、ソースコードをテキストエディタで開いてみると、素人目にももうちょっとスッキリと書けそうなところがあるので、これを修正する。

具体的には、

- 全てのストロークは線幅以外まったく同じ設定なのに、各線幅の `<path>` エレメントそれぞれに重複して記述されてしまっている
- 各線幅の `<path>` エレメントそれぞれが個別の `<g>` エレメントの中に入ってしまっている
- 同じ線幅なのに複数の `<path>` エレメントに分かれてしまっている

このような問題を手で書き直す。

##メタデータを付記##

ダウンロードしたSVGをgzipする前にメタデータをファイル冒頭に追加する。

クリエイティブ・コモンズでライセンスしたり、元にした作品や参照写真との関係を記述したりするための RDF とか xml などが素人には理解が超難しい。
っていうか、未だによく分からない。

それでもなんとか、SVG Advent Calendar の企画者でもある rikuoさんによる一昨年のSVG Advent Calendar 2014 参加記事などを参考にさせていただき、

[SVG画像にRDFでメタ情報を記述する：CCライセンスや派生元作品など - 聴く耳を持たない(片方しか)](http://d.hatena.ne.jp/rikuo/20141223)

一応は [W3C RDF Validation Service](https://www.w3.org/RDF/Validator/) でチェックしても「Your RDF document validated successfully.」という結果を得る。

##完成##

最後にgzip圧縮をして完成。
最終的なファイルサイズは 15.2 KB (15,655 バイト)

今回デジタルで行った作業は以下のような流れ。

1. スキャナで元絵をデータ化し
2. ペンタブレットで上からなぞり、
3. SVGOMGで最適化し、
4. テキストエディタでそれを再・最適化しつつ、
5. メタデータを書き入れ、
6. 最後にgzip圧縮。

#ファイルサイズ比較#

下絵にしたスキャン画像、 A4原寸1200dpiのモノクロ2値 PNGファイルのサイズは 979 KB (1,003,421 バイト) なので、gzip後のファイルと比較すると、

1003421 / 15655 = 64.0958799106 

約 64分の1 のサイズ。でもまあ、この比較は下絵用のスキャン解像度が不必要に大き過ぎたっていうだけなので全然意味無い。

本当に知りたかったのは以下のような場合の比較。

- 同じようなファイルサイズのビットマップ画像との比較
- 同じような品質の自動変換されたSVG画像との比較

##ビットマップ画像形式と比べて##

今回の作品のgzip後の最終的なファイルサイズである 15.2 KB と同じサイズで JPG, GIF, PNG 各形式でならどのくらいのクオリティの画質が得られるのかをみてみる。

結果は以下の通り。

- ファイル形式: 解像度 (画質設定 / gzipしないサイズ > gzipしたサイズ)
- JPG: 272 x 370 px (圧縮: 低品質 / 15.7 KB > 15.3 KB)
- GIF: 260 x 354 px (色数: 8色 / 15.3 KB > 15.4 KB)
- PNG: 250 x 340 px (色数: 8色 / 15.2 KB > 15.2 KB)

SVGファイルと違ってこれらの形式はgzip圧縮してもほとんどファイルサイズが変化せず、むしろ微妙に増えたりもする。

実際の画像の埋め込み表示。上から順に JPG, GIF, PNG

![JPG](https://s3-ap-northeast-1.amazonaws.com/tksh/201612_002-272x370px-LowQuality.jpg.gz)
![GIF](https://s3-ap-northeast-1.amazonaws.com/tksh/201612_002-260x354px-8color.gif.gz)
![PNG](https://s3-ap-northeast-1.amazonaws.com/tksh/201612_002-250x340px-8color.png.gz)

##自動変換されたSVGファイルと比べて##

今回の作品の下絵にしたのと同じスキャン画像を元に、ビットマップ形式からベクター形式への自動変換ツールである「[Portrace](potrace.sourceforge.netgg)」のWebアプリ版、「[Vectorization.org](http://www.vectorization.org/)」で PNG (アップロードリミットである長辺3000pxにリサイズ) から SVG への変換をし、さらに出来上がったファイルをSVGOMGで最適化する。

結果は 91.4 KB 。実際の画像はこちら。

![201612_001-2619x3000px-Vectorization.org-SVGOMG](https://s3-ap-northeast-1.amazonaws.com/tksh/201612_001-2619x3000px-Vectorization.org-SVGOMG.svg.gz)

https://s3-ap-northeast-1.amazonaws.com/tksh/201612_001-2619x3000px-Vectorization.org-SVGOMG.svg.gz

品質的には、大きく表示した場合には均一なストロークではなく微妙な線質が再現されるので、やはり絵としては良いものとなる。
けれど、データの作りが複雑なので、小さく表示する場合には細かな線が潰れ気味になってしまう感じが多少ある。

91.4 KB というのは今回の手描きSVGファイル 15.2 KB のほぼ 6倍 。

つまり、自分の手作業で移植することによって、機械による自動変換の 6分の1 のファイルサイズで似たような品質が実現出来たということ、かな？
何をもって、「似たような品質」とするかは主観的で曖昧な領域なので断言はし難い。

##最適化や圧縮による違い##

補足として、SVGOMGでの設定の違いによって生まれる差についてのメモ。

SVGOMG で「Merge paths」の項目をオフにすると、1本のストロークが `<path>`エレメント1つとなるので、例えば、ソースコードを「path」というワードで検索すれば自分が引いた線の数が分かったりして面白い。今回の作品だと、線の総本数は1772本。こんな数字はアナログだけで描いていたときには想像だにしないこと。

だけど、無駄な記述の重複は当然多くなってしまうのでファイルサイズは 30 KB くらい増える。

- 「Merge paths」 オン: 36.6 KB
- 「Merge paths」 オフ: 67.5 KB

でも結局、さらに両方をgzipした後には 1 KB くらいしか変わらない。

- 「Merge paths」 オン, gzipped: 15.2 KB
- 「Merge paths」 オフ, gzipped: 16.6 KB

#まとめ#
##アナログ段階からの心掛けが大事##

なるべく記述のシンプルなSVGにしたいと考えていたので、アナログ絵の制作段階から

- なるべく曲線を使わないように、
- なるべく線の強弱を付けないように
- なるべく線の太さを少ない数に収斂出来るように
 
ということは考慮して描いていた。
そのおかげで、そこそこスムーズにA/D変換出来たと思う。

とはいえ、線の重なりが幾重にもあって複雑な箇所は自分自身による模写であるにも関わらず上手く再現できなかった部分があった。

今後はこれを踏まえて

- SVGにしたときに軽く、
- SVGにするときに分かりやすい、

という視点をさらに強く意識したアナログ絵の描き方をしてみたい。

##メタデータまでが作品、だと思う##

メタデータ記述関係はたくさん検索しても、これで完全にOK！という正解がいまいち分からなかった。
だけど、SVGというファイル形式のとても大きな特徴は

「見えるイメージであると同時に読めるソースコードでもある」

という点だと思うので、自分の著作作品とするからには、イメージとして良いか悪いかだけじゃなく、メタデータの表記方法までをちゃんと理解してソースコードの隅々までをコントロールしたい。

##参考資料について##

オバマ大統領っていう主題に特に意味は無くて、[アメリカ政府関係の著作物はパブリックドメインとして扱われる、みたいなルール](https://www.usa.gov/government-works)があるらしいし、メタデータに出典画像URLを含めるに際しても、その永続性に結構期待してよさそう、っていうだけ。今回使った写真の掲載ページは[国防総省サイト](http://www.defense.gov/Media/Photo-Gallery?igphoto=2001294796)にも[Flickr](https://www.flickr.com/photos/thejointstaff/21837524119/)にもある。


#最後に#

ほどよく写実的でありつつ、かつデータも軽い、という今まであまり無かったいい感じの折衷点に達せれたかなと個人的にはかなり満足していますが、僕が知らないだけで同様のパフォーマンスを得られる自動変換プログラムは既にどこかに存在しているかも、という気もしています。もしなにかそのようなツールをご存知の方はぜひともご教授ください。
今回のような作業は単純に楽しくてやってはいるのですが、もし機械でもっと上手くやれることが確定しているのならば、自分はなにか他のことを探してやりたいなとも思いますので。
どうぞよろしくお願いします。

また、Githubにファイルをアップロードしました。
もっとデータを軽くするためのアイディアなどがあれば教えていただきたいですし、あるいは他になにかの素材として遊んでもらえれば幸いです。
メタデータ内の著作者名とクリエイティブ・コモンズ・ライセンスの部分だけを削らないで保持してもらえれば（もしくは、やむなく削る場合はどこかにキャプションとして付記してもらえれば）どのような改変も転載もご自由にどうぞ。

https://github.com/tksh/Pure-Stroke-SVG-Portrait