Advent Calendar 3日目:SVG画像を1バイトでも削るためのコードゴルフ


このエントリーはGraphical Web Advent Calendar 2013 への参加記事です。
今日は12月3日、ということで Advent Calendar の3日目は私id:rikuoが担当します。今回はSVG画像ファイルを1バイトでも削るためのコードゴルフのTipsを紹介していきます。

コードゴルフって?

まずコードゴルフとはなにか?の説明から。
ゴルフをしているイラスト
コードゴルフとは任意のソースコードを出来るだけ短く書くことを目的にしたものです。そのコードの動作を損なわなず、かつ可能な限り短縮して記述する手法を試行錯誤していく様子が、ゴルフのように少ない打法で競うところに似ていることからこのように呼ばれています。
またそれを競技としたコンテストも催されていますね。

画像のファイルサイズ低減策

JPEG、GIF、PNGといったビットマップ画像であればファイルサイズを低減する方法やソフトウェア・ツールは既にいくつかあり、そうした手法についての情報というのは世の中に共有されているのですが、

ベクター画像ファイルであるSVGはいかんせん不遇の時代が長かったためか、いまいちそうした情報がまだまだ知られていないようなんですよね。例えば GoogleApple のような巨大企業であってもそうで、ビットマップ画像ならばファイルサイズ低減策を行っているのに、SVGだとこの2社でも無駄にファイルサイズが大きいままだったりします。


コードゴルフを実際やってみるよ

じゃあどれくらい削減できるのか、まずは具体的にやってみると分かりやすいでしょうから、GoogleApple で使われているSVG画像ファイルをコードゴルフ的な観点から削るとどうなるか?を実際にやってみましょう。

GoogleSVGを1/3以下にしてやりましたよ(ドヤ顔で)

Googleであれば、

天気で検索した際の

風向きの矢印にSVGを利用していますがこのファイルには無駄が多いです(ドヤ顔で)

https://ssl.gstatic.com/m/images/weather/wind_unselected.svg
元のファイルサイズ:481バイト

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="42px" height="42px" viewBox="0 0 42 42" enable-background="new 0 0 42 42" xml:space="preserve">
<polygon fill="#AEBFCF" points="27,37.5 42,20 27,4.5 18,4.5 30,16.5 0,16.5 0,23.5 30,23.5 18,37.5 "/>
</svg>

これを無駄な記述を減らして最適化を施すと
コードゴルフ後:148バイト

<svg xmlns="http://www.w3.org/2000/svg" width="42" height="42">
<path d="m27 37.5 15-17.5-15-15.5h-9l12 12h-30v7h30l-12 14z" fill="#aebfcf"/>
</svg>

と1/3以下にファイルサイズを低減できました。



AppleSVGは約半分になったわー(ドヤ顔で)


Appleだとこのフッター部分のロゴに使われているのがSVGなんですが

http://images.apple.com/global/elements/breadory/breadcrumb_home.svg
元のファイルサイズ:1679バイト

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
	 width="30px" height="93px" viewBox="0 0 30 93" enable-background="new 0 0 30 93" xml:space="preserve">
<g id="Layer_1_1_">
</g>
<g id="Layer_2">
	<g>
		<path fill="#777777" d="M11.971,43.694c-1.068,0.806-1.6,1.774-1.597,2.905c0.004,1.352,0.668,2.387,1.993,3.107
			c-0.353,1.091-0.864,2.042-1.536,2.851c-0.671,0.812-1.285,1.217-1.841,1.219c-0.263,0-0.62-0.09-1.073-0.272l-0.218-0.087
			C7.254,53.23,6.86,53.143,6.52,53.143c-0.323,0.002-0.676,0.074-1.059,0.219l-0.273,0.104l-0.344,0.149
			c-0.27,0.116-0.544,0.174-0.821,0.175c-0.65,0.002-1.369-0.562-2.158-1.696c-1.137-1.622-1.707-3.393-1.712-5.31
			c-0.004-1.363,0.346-2.461,1.05-3.296c0.704-0.834,1.638-1.253,2.802-1.257c0.436-0.001,0.842,0.083,1.222,0.25l0.26,0.111
			l0.273,0.118c0.243,0.108,0.44,0.162,0.589,0.162c0.192,0,0.405-0.048,0.638-0.144l0.358-0.149l0.266-0.104
			c0.425-0.165,0.895-0.248,1.409-0.25C10.242,42.22,11.225,42.71,11.971,43.694z M9.067,38.782
			c0.014,0.173,0.022,0.307,0.023,0.401c0.002,0.857-0.292,1.61-0.879,2.259s-1.271,0.973-2.052,0.975
			c-0.023-0.193-0.036-0.332-0.036-0.416c-0.002-0.729,0.27-1.414,0.816-2.054c0.544-0.641,1.177-1.016,1.897-1.127
			C8.888,38.81,8.965,38.797,9.067,38.782z"/>
	</g>
	<polygon fill="#DDDDDD" points="5.656,93 4.516,93 28.875,46.418 5.297,0 6.406,0 30,46.425 	"/>
</g>
</svg>

この画像はAdobe Illustratorから出力したまま使っているので特に無駄な要素が多いんですよね。これもコードゴルファーな観点から見直すと
コードゴルフ後:875バイト

<svg viewBox="0 0 3e4 93e3" width="30" xmlns="http://www.w3.org/2000/svg" height="93">
<path d="m11971 43694c-1068 806-1600 1774-1597 2905 4 1352 668 2387 1993 3107-353 1091-864 2042-1536 2851-671 812-1285 1217-1841 1219-263 0-620-90-1073-272l-218-87c-445-187-839-274-1179-274-323 2-676 74-1059 219l-273 104-344 149c-270 116-544 174-821 175-650 2-1369-562-2158-1696-1137-1622-1707-3393-1712-5310-4-1363 346-2461 1050-3296 704-834 1638-1253 2802-1257 436-1 842 83 1222 250l260 111 273 118c243 108 440 162 589 162 192 0 405-48 638-144l358-149 266-104c425-165 895-248 1409-250 1222-5 2205 485 2951 1469zm-2904-4912c14 173 22 307 23 401 2 857-292 1610-879 2259s-1271 973-2052 975c-23-193-36-332-36-416-2-729 270-1414 816-2054 544-641 1177-1016 1897-1127 52-10 129-23 231-38z" fill="#777"/>
<path d="m5656 93e3h-1140l24359-46582-23578-46418h1109l23594 46425z" fill="#ddd"/>
</svg>

元のファイルサイズから比較すると52%まで削減できました。


このような感じでファイルサイズを削減する手法の紹介と、そのテクニックの原理や仕様ではどう定義されているかなど解説をしてゆきます。

Adobe Illustratorの設定を見直す

実はそうしたコンセプトで、昨年のAdvent Calendarでも記事を書いていました。

SVG画像を1キロバイトでも削るダイエット術!
特にSVG画像制作でよく使われるAdobe Illustratorの設定を見直すことで、無駄に大きくなるファイルサイズを低減する、という趣旨でした。
今回はSVGの仕様を参考にしつつ、それよりもさらに無駄な部分を1バイトでも見逃さずに鬼のように細かく削っていく技の紹介という上級者向けの内容になっています。
なので、初心者には難しい記事ですから、その点はご了承ください。
そもそもSVGってなに?という人向けの記事も以前 書いたのでそちらもよければ是非。
SVGってなに?の説明と、SVGの学習に役立つサイト紹介


……というわけで長くなりましたがここまでが前置きで、ここからが本題。

続きを読む