SVGファイルの利用

ブラウザーと表示品質

さて、最後は各ブラウザーにおける、SVGの表示品質についてです。実は、これが記事の本題だったりします。

ベクトル図形と解像度

まず、理論的な背景ですが、SVGのような「ベクトル図形はビットマップ画像とは違い、解像度の制約を受けない」と言われます。先に、CorelDRAWの「幅/高さ/単位」オプションの解説で、サイズや単位は画質に関係が無いと豪語したのも、これと関係があります。

ベクトル図形は、松本清張的な「点と線」で構成されたオブジェクトですが、そうした点や線を「描け!」という”指令”をデータ化したものです。

ベクトル図形の構造
ベクトル図形の構造。ノードと呼ばれる点と、それを結ぶセグメントで構成される。セグメントの曲線形状は、方向線によって決められる。

その指令に従って、パソコンはアプリケーションを介してディスプレイやプリンターに、線を描かせます。拡大しろだの縮小しろだのと、色々と注文が多くても、黙ってその指示に従い、その都度描き直します。

そして、描かれる線の精度は、描くものの精度(解像度)によって、変わります。粗く描くものを使えば粗く、詳細なものを使えば詳細になるのです。一般にプリンターの方がディスプレイより高精度で、商業印刷ではさらに解像度が高くなります。ですから、商業印刷物の方が、ベクトル図形の線はきれいに出力されます。

ベクトル図形描画指令
ベクトル図形描画指令の概念図

ようは、てきとうなヤツが描けば汚く、(私のように)几帳面な人が描けば美しくということですが、「それって、几帳面さ(=解像度)に依存しているってことでは?」と言っているようにも思えます。しかし、見方を変えれば、「描く人によってどうとでもなる」ということは、「描く人の几帳面さはどうでもよい=解像度に依存しない」、という理屈なのです。そして、「描け!」指令そのものは、几帳面さの彼岸に、普遍的存在として君臨します。

SVGとしては、「下手でも上手でも、とにかく線を引け」と命じ、ディスプレイが「とりあえず、てきとうに引いておくか」、プリンターが「わかりました、早速きれいに線を引きましょう」と応じても、もう後は野となれ山となれ、SVGは命令したことに満足してあとはお構いなし、とでも言えばよいでしょうか。

ビットマップの原理

ただし、几帳面さは違えども、描く人がいなければ、いくら普遍的指令であっても、ベクトル図形は人の目に見える「絵」にはなりません。そして、多少原理は違えども、ベクトル図形を描くキャンバスは、“ビットマップ画像”なのです。ディスプレイ画面はピクセルにほぼ相当するカラーセルで、印刷機はインクの点で、ビットマップを描きます。ビットマップが無ければ、ベクトル図形はただの理念に終わってしまうのです。

ビットマップの原理をここで紐解くと、一般的には正方形のマス目による集合体で、ひとつひとつの正方形を「画素」と呼びます。画素の英語表現が、「ピクセル」です。このピクセルに色を指定し、絵柄を構成します。

ビットマップ画像の構造図
ビットマップ画像の構造。ピクセルというマス目で構成されている。

24bitフルカラー画像の場合、使える色は約1677万色ありますが、ひとつのピクセルに着けられる色は、そのうちの1色だけです。1色で、1つの正方形全体を塗りつぶします。1つの正方形の中を、異なる色で分けることはできません。

ピクセル分割の不可
この図で例示しているような、1つの正方形(ピクセル)の中を分割して塗りつぶすことは、ビットマップではできない。

ですから、ピクセルの最小単位は「1」です。1/2ピクセルとか、0.5ピクセルといった半端なものは、CorelDRAW上では(普遍的指令として)設定できても、画面に書き出すことはできません。

つまり、ピクセルのマス目にぴったり収まらない線は、てきとうにごまかされることになります。特に曲線は、四角のマス目では絶対に表現できませんから、資本主義生産様式の価値増殖と同じように、すべてごまかしで成り立っています。

レンダリングの処理

ごまかす方法は、ピクセルの見かけのサイズ小さく設定して、目立たなくさせることです。それとともに、収まらない部分を目立たなくさせるような色で塗りつぶす処理です。こうした塗りつぶしによるごまかしを、「アンチエイリアス」処理と呼びます。

アンチエイリアス処理の概念図
ピクセルに納まらない部分は、近似色で塗りつぶす。これがアンチエイリアス処理。

そして、アンチエイリアスを含めた、画面に出力する処理が「レンダリング」です。ブラウザーは、HTML、CSS、そしてSVGの指令に従って、その内容を画面にレンダリングしているわけです。ようは、ブラウザーがどのようなアンチエイリアス処理を加えてレンダリングするかによって、SVGの線の画質が決まるということです。

表示の比較

img要素

では、ここで(遂に)各ブラウザーの画質を比較してみましょう。「パノプティコン」を以下の設定でSVGに書き出し、img要素で表示させています。

  • 互換性: SVG 1.1
  • エンコード方法: Unicode – UTF-8
  • スタイルのオプション: 内部のスタイルシート
  • 幅/高さ: 630ピクセル
  • 描画の精度: 1:100単位
  • グラデーションのステップ数: 128

JavaScript、テキスト、ビットマップは含まれていません。

また、動作環境は以下のとおりです。

  • CPU: Intel Core i7 3770K
  • メモリ: 32GB
  • ビデオカード:
    • Nvidia GeForce GTX 690 4GB
    • Nvidia GeForce GTX 660 2GB
    • ドライバ: GeForce 314.22 Driver
  • OS: Windows 8 Pro 64bit
  • ブラウザー:
    • Internet Explorer 10
    • Firefox 19.0.2
    • Opera 12.14
    • Chrome 26.0.1410.43 m
IE10の表示結果
IE10の表示結果
Firefoxの表示結果
Firefoxの表示結果
Operaの表示結果
Operaの表示結果
Chromeの表示結果
Chromeの表示結果。正しくレンダリングされていない。

このうち、Chromeはちょっと変です。

background-image

次は、SVGと同サイズのdiv要素に、background-imageで表示させた結果です。

4つのブラウザーの表示結果
各ブラウザーの表示結果。やはり、Chromeは正しくレンダリングされていない。

img要素の場合とほぼ同じ結果なので、左上1/4だけを掲載しています。

この結果でも、Chromeだけおかしな表示です。

background-size

次は、SVGのサイズを幅/高さ315ピクセルにして書き出し、630×630ピクセルのdivにbackground-imageで表示するとともに、background-size:coverで630ピクセルに拡大(2倍)した場合です。

IE10の表示結果
IE10の表示結果
Firefoxの表示結果
Firefoxの表示結果
Operaの表示結果
Operaの表示結果。ぼやけてしまっている。
Chromeの表示結果
Chromeの表示結果。これも正しくレンダリングされていない。

相変わらずChromeは変ですが、Operaもぼやけてしまいました。

表示結果の検討

さらに、[Ctrl]+[マウスのスクロールボタン回転]で表示サイズを拡大/縮小すると、FirefoxもOperaと同じようにぼやけます。

Firefoxの表示結果
スクロールボタンでズームインしたFirefoxの表示結果。Operaのようにぼやけている。

といっても、Operaのようにどのズーム倍率にしてもぼやけているわけではなく、ぼやけるときとそうでない倍率があります。

ずっとおかしかったChromeも、特定の倍率できちんとした表示になるときがあります。さらに不可思議なことに、(background-sizeの場合も含め)background-imageで表示した場合、div要素にborderプロパティで輪郭線を付けると、まともな表示になります。

Chromeの表示結果
div要素にborderを指定した場合のChromeの表示結果。なぜか、この条件では正しくレンダリングされている。

ただし、img要素にborderを付けても、変わりませんでした。このように、Chromeは、様々な条件によって表示がおかしくなるという、まさに不安定の極致です。

一方、IE 10は、拡大/縮小でややぼやけることもありますが、Firefoxほどの破綻はありません。

IE10の表示結果
スクロールボタンでズームインしたIE10の表示結果。やや輪郭がぼやけているように見えるが、OperaやFirefoxほどではない。

これらの結果から、IE 10以外のブラウザーには、SVGのレンダリングにおいて、やや難点のあることが分かります。特にChromeは、どうしようもありません。

唯一、IE10だけが、ほぼ正常に、どのような条件でもSVGのレンダリングができています。「SVG表示ならIE10」と、太鼓判を押せます。

「パノプティコン」は、ベクトル図形の曲線だけで構成されているので、いかなる方法で拡大/縮小を行おうとも、普遍的指令にぶれはありません。しかし、そもそもピクセルのマス目に納まらない曲線形状だけでなく、出力先で線の幅が1ピクセルを下回ったり、やはり線と線の間隔が1ピクセルを下回ったりした場合などにはごまかして、それらしくレンダリングする必要が出てきます。その手法が、IE10以外のブラウザーでは、精度が低いということです。

まとめ

実は、SVG画像を多用していると、IE10以外のブラウザーで度々、画像が汚くなることがありました。たとえば、ページ全体の背景中央に垣間見える、「パノプティコン」のイラストがそうです。「表示の比較」で例示したとおり、Chromeでは薄汚い線でイラストが表示されてしまいます。これも、background-repeatをrepeatにする(デザイン上の理由により、現設定はno-repeat)と、なぜか直るのです。そうした、不可解な発生条件を調べることが第一の目的だったのですが、そのついでにSVG自体や、ベクトル図形の原理の解説も、目論んでみた次第です。

例によって長くなりましたが、SVGベクトル図形の画質は、「サイズ変更では影響を受けない、それを描くものによって決まる」、という真理が、ここに証明されたということで、この記事を締めくくりたいと思います。

krzm.jp:not(so-called mobile friendly)