SVG画像を書き出す際に重要な設定「小数点以下の桁数」とはなにか?

これはSVG Advent Calendar 2014の参加記事です。
昨日はmemocarilogSaori Miyazakiさんによる「filter 要素の基本的な使い方と filter 要素をつかったモノクロからカラーへ変化するマウスオーバー効果を作る方法」でした。
第3日目は私 id:rikuo が担当します。
(※追記)第4日目はイロドルハナ(@shino212)さんの「はじめてSVGでアニメーションを作った時の話」です。
ちなみにまだ空いている枠はあるので、興味のある方は是非ご参加ください。


はじめに

SVGXMLをベースにしているためテキストエディタでも簡単に作れるとは言え、実際の制作は何らかのオーサリングツールを利用することがほとんどでしょう。
中でもAdobe Illustratorベクター系ソフトウェアの代表的な存在で広く普及しています。このIllustratorからSVGを書き出す際に様々な設定が変更できますが特にSVGのファイルサイズと品質に大きく影響を与えるのが「小数点以下の桁数」です。
今回はこの項目をピックアップして、その仕組みや注意点などを解説していきます。

項目の場所と、初期値

Adobe IllustratorからSVGで保存する際には「SVGオプション」ダイアログが表示されます。

初めて利用する際には簡略な設定しか表示されませんから、「詳細オプション」をクリックして詳しい項目を出しましょう。
詳細なSVGオプションダイアログの中央くらいにあるのが「小数点以下の桁数」です。

初期設定値は1。
つまり「詳細オプション」を表示させないまま初めて使う場合は自動的に1になります。
そしてマウスカーソルを重ねると表示される説明文がこちら。

書き出したアートワーク内のベクトルの精度を1から7の範囲で指定します。値が大きいほどファイルサイズが大きくなり画質が向上します。ほとんどのファイルでは、3が最適です。

この文章だけでは
『3が最適なはずなのに、なぜ1が初期設定値なのだろう?』
とか、
ベクター形式なら拡大しても画質が綺麗なのが特徴じゃないの?』
と疑問に感じるかもしれません。そもそもベクトルの精度とはなにか?とか。


それらを理解するためにも、ベクター形式とはどういう仕組みで図を保存するのか?といった辺りから説明していきましょう。

ベクター形式の仕組みの簡単な解説

現在よく使われている画像形式、JPEG,GIF,PNGファイルはラスター(ビットマップ)形式です。ラスター形式はものすごく単純に言ってしまえば様々なピクセル(ドット)を並べて描く形態です。

そのピクセルがどんな色か、またいくつ並んでいるのかを記録・保存することで一つの画像として扱えるわけです。
ピクセルの数が少ないと古いゲームのようなドット絵になりますし、ピクセルの密度が多くなればデータ量は大きくなりますが写真のような詳細な描写も可能になります。


ラスター系に対してAdobe Illustratorベクター系またはドロー系と呼ばれるのソフトウェアです*1SVGはScalable Vector Graphicsの略ですからもちろんベクター系。
ではベクター系ではどのように図を記録・保存しているでしょうか。

例えばこうした直線があるとします。
これは点Aと点Bを結んだ直線であると考えられますね。

SVGでこの直線を示すとすると

<svg>
	<path d="
		M 点Aの X座標,Y座標
		L 点Bの X座標,Y座標
 	"/>
</svg>

といった形式で記述できます。
path要素はSVGでは直線やベジェ曲線を描く要素です。
そしてpath要素のd属性にコマンドと座標を示して図形を描写します。
Mはmoveto、つまり移動のコマンドで、描きはじめる始点の位置を指定します。
Lは直線を描くlinetoのコマンドで、続いて点BのX座標・Y座標を書くことで点A-Bを結ぶ線が引かれます。


ベクター形式ではこのようにして、点(Illustratorの用語だとアンカーポイント)の座標を記録していくことで図形を扱えるわけです。




基本をふまえた上で、もう少し具体的にSVGの記述の仕方を見てみましょう。
先ほどの直線を実際にSVGで書くとこのような感じになります*2。ちなみにSVGは左上が原点0です。

<svg width="200" height="200">
	<!-- 
		Moveto 点Aの X座標,Y座標
		Lineto 点Bの X座標,Y座標 -->
	<path d="
		M 46.6642685	,66.3755875
		L 163.1642761	,168.3755798
	"/>
</svg>

注目するポイントは、座標の値が小数点以下 7桁まで記述されていますね。これは冒頭に書いた「小数点以下の桁数」を7にして書き出したためです。
もしこれを1にして書き出した場合はどうなるか?というと今度はこうになります。

<svg width="200" height="200">
	<!-- 
		Moveto 点Aの X座標,Y座標
		Lineto 点Bの X座標,Y座標 -->
	<path d="
		M 46.7	,66.4
		L 163.2	,168.4
	"/>
</svg>

随分表記が短くなりましたね。
「小数点以下の桁数」はこのように、ベクター形式で重要な座標の詳細さを変更します。

例えばこの単純な一つの直線を記述したSVGファイルは

小数点以下の桁数 ファイルサイズ 実際のファイル
小数点以下の桁数 1 288バイト line_1.svg
小数点以下の桁数 7 312バイト line_7.svg

と24バイトの差がでます。
この直線の描写には2個の点しか使われていませんが、それぞれx座標,y座標の値がありますから1桁と7桁の差が6で
6×4 = 24
で24バイトの差になったわけです。
ただし、もちろん小数点以下の桁数が多いほど正確な数値になります。

46.6642685
46.7

厳密な数値としては桁数が多いほど良い、しかしその反面それぞれの図形ごとに記述されるデータ量も増えていくため全体のファイルサイズに大きな影響が現れます。
では具体的にそれが一体どのように違いとして現れるのか?というのはその画像によって異なるために一概に言えないので、いくつかの画像で実際に試してみました。

様々なイラストでの比較

SVGファイルと言ってもイラストの画風や技法によって傾向は異なります。今回は色々にテイストを変えてイラストを制作してみました。ファイルはいずれもAdobe Illustrator CC 2014から出力したままのもので計測を行いました。


イラスト 1

まずはアイコンっぽい単純なデザインのイラストから。
ベクター系のイラストと言ったらやはりトラだろ、ということで。

このイラストで使われているアンカーポイントの数*3は103。このファイルを「小数点以下の桁数」の設定を変更して出力し、ファイルサイズの変化を比較します。

小数点以下の桁数 ファイルサイズ
小数点以下の桁数 1 3.42 KB
小数点以下の桁数 2 3.94 KB
小数点以下の桁数 3 4.43 KB
小数点以下の桁数 4 4.87 KB
小数点以下の桁数 5 5.37 KB
小数点以下の桁数 6 5.85 KB
小数点以下の桁数 7 6.29 KB

詳しい比較ページ
ちなみに今回は敢えて重いSVGファイルを作成しているので、このページではPNG画像を代替として表示しています。実際のSVGファイルは比較ページで確認してください。


イラスト 2

ベクター系のイラストと言ったらやはりトラだろ その2

このイラストのアンカーポイントの数は2983。

小数点以下の桁数 ファイルサイズ
小数点以下の桁数 1 77.8 KB
小数点以下の桁数 2 95.1 KB
小数点以下の桁数 3 110 KB
小数点以下の桁数 4 127 KB
小数点以下の桁数 5 143 KB
小数点以下の桁数 6 159 KB
小数点以下の桁数 7 175 KB

詳しい比較ページ2
なお、このトラのイラストはパブリックドメインで公開されているこちらの写真を元に作成しました。

File:Panthera tigris tigris.jpg - Wikimedia Commons
(by John and Karen Hollingsworth , Zwoenitzer)

イラスト 3

ベクター系のイラストと言ったらやっぱりトラ その3

写真を元にポリゴン風にレタッチしました。アンカーポイントの数は9675。

小数点以下の桁数 ファイルサイズ
小数点以下の桁数 1 330 KB
小数点以下の桁数 2 357 KB
小数点以下の桁数 3 381 KB
小数点以下の桁数 4 410 KB
小数点以下の桁数 5 438 KB
小数点以下の桁数 6 463 KB
小数点以下の桁数 7 490 KB

詳しい比較ページ3
こちらのトラもパブリックドメインの写真を元に作成しました。
撮影は同じくHollingsworth夫妻。

File:Siberian tiger panthera tigris altaica mammalia carnivora felida.jpg - Wikimedia Commons
(by John and Karen Hollingsworth)
夫妻はアメリカ合衆国魚類野生生物局の職員とのことで、合衆国著作権法により職務上作成した著作物は著作権法の保護対象にならずパブリックドメインとして扱われます*4

イラスト 4

ベクター系の(略)その4

アンカーポイントの数は27995
同じトラの写真を、Illustratorの「画像トレース」機能でベクター化したものです。

小数点以下の桁数 ファイルサイズ
小数点以下の桁数 1 795 KB
小数点以下の桁数 2 992 KB
小数点以下の桁数 3 1.14 MB
小数点以下の桁数 4 1.30 MB
小数点以下の桁数 5 1.48 MB
小数点以下の桁数 6 1.64 MB
小数点以下の桁数 7 1.81 MB

詳しい比較ページ4

イラスト 5

最後はトラでは無いですが、線画で重いものを

アンカーポイントの数は64291。パスの数は31198とかなり細かく描いたイラストです。

小数点以下の桁数 ファイルサイズ
小数点以下の桁数 1 1.82 MB
小数点以下の桁数 2 2.08 MB
小数点以下の桁数 3 2.33 MB
小数点以下の桁数 4 2.58 MB
小数点以下の桁数 5 2.82 MB
小数点以下の桁数 6 3.06 MB
小数点以下の桁数 7 3.31 MB

詳しい比較ページ5

こちらはオーストラリアのブリスベン市のアカウントでFlickrに投稿された写真を元に作成しました。ライセンスはCC-BY 2.0

この写真を元に作成したイラスト自体もクリエイティブコモンズライセンスを付けて以前に公開しています




以上、様々なイラストで比べてみました。
一覧にすると

アンカーポイント 103 2983 9675 27995 64291
桁数 1 3.42 KB 77.8 KB 330 KB 795 KB 1.82 MB
桁数 2 3.94 KB 95.1 KB 357 KB 992 KB 2.08 MB
桁数 3 4.43 KB 110 KB 381 KB 1.14 MB 2.33 MB
桁数 4 4.87 KB 127 KB 410 KB 1.30 MB 2.58 MB
桁数 5 5.37 KB 143 KB 438 KB 1.48 MB 2.82 MB
桁数 6 5.85 KB 159 KB 463 KB 1.64 MB 3.06 MB
桁数 7 6.29 KB 175 KB 490 KB 1.81 MB 3.31 MB

イラストで使われているアンカーポイントの数に比例してファイルサイズに差が大きく出る、というのが分かりますね。


転送速度・閲覧環境を考えるならばファイルサイズが少ないほど良いですから、
このことから
『小数点以下の桁数は1がベストだな!』
と素直に捉えがちなんですが……、実はなかなかそう断言できない部分もあります。

小数点以下の桁数を減らすことで失われるもの

これは先のイラストをChrome上で500%に拡大して、それぞれのファイルを比較したアニメーションGIFファイルです。

「小数点以下の桁数」1〜7までのイラストを続けて比較。


分かりやすく、「小数点以下の桁数」が1と3のファイルを比較したもの。

こうして比べてみると理解しやすいのですが、かなりずれがありますね。
これは小数点以下の桁数が少ない……つまり座標が四捨五入されてしまうためです。


この図のことを思い出してみてください。

<svg width="200" height="200">
	<!-- 
		Moveto 点Aの X座標,Y座標
		Lineto 点Bの X座標,Y座標 -->
	<path d="
		M 46.6642685	,66.3755875
		L 163.1642761	,168.3755798
	"/>
</svg>

小数点以下の桁数が7桁だとこのような数値になりましたね。
これが1桁だと

<svg width="200" height="200">
	<!-- 
		Moveto 点Aの X座標,Y座標
		Lineto 点Bの X座標,Y座標 -->
	<path d="
		M 46.7	,66.4
		L 163.2	,168.4
	"/>
</svg>

こうでした。
つまりこれは

このように四捨五入によって本来の座標からずれてしまっている、というわけです。
Webページで表示されるのが作成サイズの等倍程度だと描画の差は気になりませんが、大きく拡大する用途であればこの点は注意が必要なポイントです。


このずれは細いフォントで影響が大きいです。

アンカーポイントの数は595。(デモページ
比較のアニメーションGIF



「小数点以下の桁数」が1と3のファイルを比較したもの。

比較すると字の形が歪んでいるのが分かりやすいですね。




そして特に顕著なのが上でも紹介した写真を「画像トレース」でベクター化したようなタイプのイラスト。
「小数点以下の桁数」1から7まで比較したアニメーションGIF



「小数点以下の桁数」が1と3のファイルを比較したもの。

塗りと塗りとの間に隙間ができてしまっていますね。
これはIllustrator上ではピッタリと隣り合って面を分割しているのですが

SVGに出力する際に、座標の値を四捨五入で丸められてしまうためにこうしたずれが起きてしまいます。「画像トレース」機能以外にも面を分割することは少なくないので、そうした際には気をつけましょう。



まとめ

というわけで、SVGを書き出す際の「小数点以下の桁数」の設定による違いの検証でした。
まとめると

  • ファイルサイズの観点からは「小数点以下の桁数」は少ないほど良い
  • しかし一方で画質の観点からは少な過ぎると図形が歪む

と言えるでしょう。
これはトレードオフの関係でどうバランスを取るか、悩ましい点です。
とは言えJPEG画像でも圧縮率を高めるとファイルサイズは減るがブロックノイズが目立つ、といったようにラスター形式と似たような状況であります。


では「小数点以下の桁数」はいくつが適切なのか?というと、断言は難しいところです。SVGファイルと言ってもアイコンとして使うか?イラストとして配置するか?利用者が拡大をどれくらいするか?といった様々な活用の仕方がありますし、それに小数点以下の数値だけでなく全体の画像領域の大きさも画質には大きく左右されるので、一概にこうだ!とは言い難いです。
ただ今回は特に図形が歪みやすい例を示しましたが基本的には ずれはそこまで大きな問題にはならないので、
普段は「小数点以下の桁数」は1にして、歪みやすいケースでは3くらいに上げる
という使い方で良いんじゃないかと。
また一方で多くの場合、「小数点以下の桁数」が4以上は過剰でしょう。ファイルサイズとの兼ね合いを鑑みると4〜7は必要以上な画質です。


いずれにせよ、SVGファイルを作成した際に妙なずれや隙間をみつけたときにはこの辺りの設定を見直してみてはいかがでしょうか。



おまけ

以前に書いたSVG関連記事です。

SVGを制作できるアプリ,お絵描きソフトを徹底的に調べました! 114個






あと、以下はダラダラとした蛇足・補遺です。

蛇足・補遺

小数点以下の桁数が8桁以上の数値もできるか?

できます。
(例 その1)

<svg width="200" height="200">
	<path d="
		M 46.66426851	,66.37558753
		L 163.16427614	,168.37557982
	"/>
</svg>

Adobe Illustratorからの書き出しが小数点以下の桁数1〜7の範囲なのであって、8桁でもSVGの仕様上は可能です。……ただ仕様はともかく、ブラウザの描画処理上ではどう扱われるかは分かりませんが。あまりに桁数が多いと内部処理では四捨五入されて描画しているのかもしれません(未検証)。

小数点以下の桁数が0、つまり整数でもいいのか?

良いです。
(例 その2)

<svg width="200" height="200">
	<path d="
		M 47	,66
		L 163	,168
	"/>
</svg>

Adobe Illustratorからの書き出しが小数点以下の桁数1〜7の範囲なのであって(2度目)、座標の値は整数でも構いません。昨年に書いたコードゴルフの記事でも座標の精度はそのままで、整数に変更する手法を使っています。
viewBox属性の数値を1000倍にして小数点を削る - SVGのコードゴルフ

小数点以下の桁数が異なるものが混在していてもいいのか?

良いです。
(例 その3)

<svg width="200" height="200">
	<path d="
		M 46.6642	,66.376
		L 163.17	,168.4
	"/>
</svg>

例えばイラストの雰囲気を決定づける繊細な表情の部分は小数点以下の桁数を多くして、背景など少しくらいずれても構わないような部分は小数点以下の桁数を少なくする、といった処理を行うこともできます。
ただし、やはりAdobe Illustratorからの書き出しにはそうした処理には対応していないため、作業には手間がかかりますが、仕様上は混在していても何ら問題ありません。

変換を繰り返すと精度が落ちる

SVGファイルに書き出し、またそのSVGファイルを読みこんでさらに編集を加えて書き出し、といった作業を繰り返していくと座標の数値が四捨五入で丸まっていき、精度が落ちていくことがあります。
1度、2度くらいならともかく回数によっては見た目で分かるほどずれが生じることもあるので注意しましょう。

ベクター形式の画像はどんなに拡大してもキレイ」か?

ベクター形式の画像の特徴についての説明で、よく

どんなに拡大してもキレイ

という紹介をしがちですし、実際に私自身も過去に何度かこう書いたこともあるのですが、この「小数点以下の桁数」の問題を理解すると分かる通り厳密には必ずしもそうとは言い切れないんですよね……。
拡大に強いのは確かに事実なものの、設定によっては精度が低いこともある、という。
私も語弊があると感じつつも分かりやすさを優先して「拡大してもキレイ」と言ってしまうのですが、かといってそうでもない状況を説明しだすと長いし……ということもあり、この記事を書いてみました。
仕様に詳しい人はともかく、デザイナーやコーダーの人がSVGを制作するときには戸惑いやすいんじゃないかなー、と思ったので。結局長い記事になってしまいましたが。

><

*1:もちろん、Adobe Illustratorはラスター系のデータも扱えますが

*2:ここでは分かりやすさを優先して、省略している記述があります。詳しい内容は実際のSVGファイルを確認してください

*3:「小数点以下の桁数」はアンカーポイントだけに限らず、ベジェ曲線の方向点なども影響を受けますがあくまで参考として

*4:ただしそうした条件でのパブリックドメインの著作物については、日本国内での著作権法上の扱いには議論もあるようです