フォントラスタライズアルゴリズムの公開(2/2)

(記事「 フォントラスタライズアルゴリズムの公開」の翻訳の第2部)

Linux


最悪の継承


Windowsはフォントのラスタライズが不十分で、Linuxはさらに悪いです。 私が見たすべてのLinuxシステムは、David Turner、Robert Wilhelm、およびWerner LembergによるFreeType [10]を使用しています。 これは優れたライブラリですが、残念ながらその使用方法を成功と呼ぶことはできません。 典型的なLinuxスクリーンショットは次のようになります。



完全なスクリーンショットは次のとおりです。
参照

問題はすぐに目立ちます-滑らかな結果として形成された丸い角の黒い斑点。 一般的に、斜めのストロークは垂直のストロークよりも重く見えるため、結果として「汚れ」の印象を与えます。 FreeTypeとLinuxはClearTypeに似たサブピクセルラスタライズを使用できると主張するかもしれませんが、私にとってこれには顕著な利点はありません。



「W」、「v」、「y」を見てください。問題は基本的に同じで、キャラクターは汚れています。 ラスタライズのプロセスでガンマ補正を使用して、コーナーの状況をわずかに改善できますが、これでも理想的な表示を実現することはできません。

ガンマ補正


ガンマ補正は次のように機能します。



ご覧のとおり、ガンマ2.0を使用すると、角が丸くなり、スムージングが非常に良くなります。 ガンマ補正は別の重要なトピックです。興味がある場合は Charles Poynton [6]のガンマFAQで包括的な情報を見つけることができます。

私たちの場合、電子回路の「ソース信号-結果」の曲線についてではなく、人間の視覚の詳細について話しているわけではありません。 視覚的な反応は、物理的な光度の平方根にほぼ比例します。 言い換えると、黒い背景に2つの白いピクセルがあり、そのうちの1つが2番目の光子よりも2倍多くの光子を放出する場合、これは2倍明るく見えるという意味ではありません。 実際、どこか1.4倍です。 これは簡単に確認できます。



右側には2つのピクセルがあり、左側のピクセルよりも1秒間に2倍の光子を放出すると自信を持って言えます。 ただし、2倍明るく見えません。 4ピクセルでは約2倍の明るさが得られますが、2倍ではありません。

不要な説明を省略して、主に2つのRGB色空間があると言うことができます。主観的に均一なsRGBと物理的に均一です。 後者では、値は物理的な光度に比例しますが、sRGBとは対照的に、値は主観的な光度に比例します。 通常、物理的に均一な色空間は、単にリニアRGBと呼ばれます。 アンチエイリアシングを使用する場合、線形空間で色の混合を行う必要がありますが、表示する前に色をsRGBにする必要があります。 実際には、このステップはしばしば無視され、アンチエイリアスはsRGBで直接実行されます。 多くの場合、これは許容可能な結果を​​もたらしますが、テキストをラスタライズするためではなく、Microsoft Wordで直接示すことができます。 トリックは、彼らがゼロから再描画するのではなく、ある種のトリックを使用してテキストを選択することです。 通常の白黒のスムージングでは、選択したテキストは汚れています。 ClearTypeを使用すると、色の境界線が取得されます。



したがって、正しいガンマ補正はWindowsで実行されますが(選択されたテキストでは実行されません)、Linuxでは通常無視されます。 FreeTypeは、ラスタライザが生成する白黒のスムージングマスクに目的のガンマ変換を簡単に適用できます。 ただし、これはWindowsと同じように機能します。色の反転はガンマの反転を生成します。 ガンマは、混合する前に各色成分に個別に適用する必要があるため、実際には役に立ちません(実際には、線形RGBでの作業と同等です)。 したがって、白黒マスクのガンマ補正は、白い背景に黒いテキストを表示する場合にのみ役立ちます。 この場合、領域2の値を修正に使用できますが、黒の背景に白のテキストを表示する場合は、ガンマ値を反転する、つまり0.5前後の値を使用する必要があります。 問題は、テキストと背景の正確な色がわからないことです。テキストはグラデーションまたは画像の上に表示することもできます。 したがって、「白黒」ガンマ補正は機能せず、「フルカラー」ガンマ補正は高価で実装が困難になる可能性があります。 問題は、リニアRGBがチャネルごとに8ビット以上を必要とすることです。そうしないと、必然的に色が失われます。 テキストの場合、これは有効かもしれませんが、デスクトップ全体でこれを要求することはできません! また、チャネルごとに16ビットを使用するリニアRGBでの作業は、依然として許容できない贅沢です。

ガンマが機能しません


実際、状況はさらに悪化しています。 同じIrfanviewでLinuxのスクリーンショットに2に等しい値のガンマ補正を適用し(画像->色の強調...)、テキストを見ることができます。 アイコンが露出過度に見えるという事実に注意を払わないようにしてください。テキストに注目してください。



好きですか 私はまだしません。 AGGでテキストのラスタライズに取り組んでいたとき、正しいガンマ補正ですべての問題を解決できると思いました。 種類はありません! どのようにうまく機能しても、一部の要素は垂直および水平ストロークよりも太く見え、一部は薄くなります。 これは、sans-serifフォント、および特にストロークがピクセル単位でハードアラインされている場合に非常に顕著です。 問題は、TrueTypeヒントがアンチエイリアスなしの通常の白黒ラスタライザ用に特別に設計されていることです! アンチエイリアシングを使用することは形式上正しくなく、ほとんどのLinuxシステムはそれを実行します。 以下の画像は、FreeTypeとGetGlyphOutline()の両方を使用したアンチエイリアスを使用したラスター化の結果です。



テキストは見栄えが悪く、Linuxでほとんどの場合に見られるものと非常に似ています。 ここではガンマ補正は役に立ちません。 たとえば、ガンマ値が1.5の場合に最高の結果が得られました。 まだ見栄えが悪い:



途中で、特定のサイズから始めて、テキストが重く見えるようになっていることに気付くはずです。 これはまさにWindowsで起こることです。 ClearTypeをオフにすると、明らかです(テキストサイズは正確に保存されません)。



一般的に、あなたはその考えを理解しました。 より明確にするために、Win32 APIからGetGlyphOutline()関数によって返されるベクトル画像を増やして、何が起こるかを確認できます。



これは、特許取得済みのアグレッシブヒントが13ピクセルの公称サイズに対してどのように機能するかです。 そのため、「k」のストロークは非常に細く見え、ほとんど見えません。 Times New Romanのイタリック体はさらに悪く、「z」の斜線が完全に消えます。 歪みは、スムージングを行わない通常のラスタライザには影響しませんが、FreeTypeを使用するラスタライザはこれらの影響を受けます。 ピクセルのカバレッジの程度を直接計算するため、斜めストローク「z」のカバレッジは正直にゼロになります。 つまり、ヒントを得るためにTrueTypeバイトコードを解釈しても意味がありません(ライセンスを購入する必要があることは言うまでもありません)。 スムージングは​​良いことですが、あなた自身のためにそれを使うべきではありません。 いずれにせよ、不適切なヒンティングと組み合わせて使用​​される場合、スムージングのないテキストを好むでしょう。

AutoType FreeType


FreeTypeバージョン2では、David Turnerが自動ヒントメカニズムを導入しました。 それは非常にうまく機能しますが、それにもかかわらず、その直接適用は理想からはほど遠い結果をもたらします。 1.5のガンマでVerdanaヘッドセットをラスタライズした結果を見てください。



非ヒンティングの例と比較してください:



ヒントなしのバージョンは間違いなくより正確に見えますが、ぼやけています。 主に3つの違いがあります。

  1. 自動ヒンティングでは、小さな丸みのある要素でもエラーが発生します(垂直ストロークと斜めストロークの視覚的な太さの違い)。
  2. 「犬」という単語の「og」のように、自動ヒンティングが誤ったカーニングにつながる場合があります(この例では、フォントのカーニングテーブルが使用されました)。
  3. 自動ヒンティングは、テキストの行全体にエラーを蓄積するという同じ問題につながり、その結果、テキストの右端が「ノッチ」になります。

Autohinterは、Times New Romanなどのより複雑なフォントでより適切に機能しますが、同じ配置の問題が引き続き発生します。

どうする?


楽しみにして、別の例を示します。



許容できる解決策を見つけることはまだ可能です! ただし、最初に、あらゆる種類のヒントを使用する方法がなく、同時に任意の縮尺でテキストの正しい位置を維持する方法がないことに同意する必要があります。 自然なぼかしを加えた、ヒントのないテキストのみ。 それでも、ラスター化は改善できますが、あまり重要ではないものを犠牲にする必要があります。 つまり、テキストの垂直方向の位置と高さをわずかに不正確にすることができます。 とりわけ、TrueTypeヒントは同じように機能します。たとえば、高さが12ピクセルと13ピクセルのテキスト行は、画面上で同じ高さになりますが、見た目は異なります。



つまり、正確な水平方向の位置を維持しながら目に優しいテキストを作成するには、次のものが必要です。

  1. LCDモニターで水平サブピクセルRGBスムージングを使用します。
  2. 垂直方向のヒントのみを使用し、水平方向を完全に放棄します。
  3. ヒンティングされていないグリフには、高解像度で計算された正確なグリフオフセット値を使用します。
  4. カーニングテーブルの正確な高解像度値を使用します。

小さなガンマ補正で結果を改善できますが、これは必要ありません。 テキストはsRGBでも直接きれいに見えます。つまり、反転配色でも問題はありません。

FreeTypeとその自動焼結により、許容できる結果を簡単に達成できます。 これは、TrueTypeの特許取得済みのヒントのライセンスを心配する必要がないことを意味します。 Win32 APIのGetGlyphOutline()関数を使用しても同じことができます。 難しいですが、それでも可能です。

RGBのサブピクセルラスタライズ


Steve Gibsonのページ、 「Subpixel Rasterization Technology」 [2]に、RGBでのサブピクセルラスタライズの使用に関する包括的なガイダンスがあります。 また、GetGlyphOutline()が生成できる64レベルのスムージングビットマップでこのテクノロジーを使用してみました。MaximShimanarev、 「Windows LonghornでのClearTypeの動作 [3](UPD:リンクは悪いですが、 こちらこちら、またはこちらで読むことができます ) 次のリンクから、すべてのソースを含むWindows用のデモプログラムをダウンロードできます。
antigrain.com/stuff/lcd_font.zip

さらに、 AGGの単純な「夕方の膝の上」のラスタライザーを作成しました。 次のデモで見つけることができます。 現時点では、コードは安全ではなく、かなり遅いです。 これはデモでは正常ですが、主にスタック内の2048ピクセル以下の一時バッファーを使用するため、実際のプロジェクトでは受け入れられません。

最も単純な場合、必要なのは各カラーチャンネルの透明度の値だけです。 このファイルでは、agg_pixfmt_rgb24_lcd.h。 また、スティーブギブソンが説明する余分なぼかしを使用しました。 実行中に実行されますが、何らかのキャッシュメカニズムを使用して事前に実行できます。 この場合、少なくとも従来のアルファブレンディングよりも遅くなく、より速く動作します。

チャネルミキシングをデバッグするには、Brian FreisenのZoomIn [9]プログラムを使用しました。 3の倍数であるすべてのスケールで、「デコード」カラーのトリプルを追加しました。 実行可能ファイルはこちらからダウンロードできます: antigrain.com/stuff/ZoomInLcd.zip (2005年に変更されたソースを失いました。いずれにしても、これらの変更は自分で簡単に行えます)。 通常の白黒およびサブピクセルRGBラスタライズの拡大結果を比較できます。


黒と白のラスタライズ


サブピクセルRGBラスタライズ

その他のニュアンス


垂直方向のヒンティングを保持するために、水平方向を取り除くために、単純にヒンターをだます:文字を水平方向に引き伸ばして、ヒンターが高精度で動作するようにします。 問題は、FreeTypeのAGGフォントエンジンが、ヒントが与えられると不正確なオフセット値を使用することです。 技術的には、ヒンターは強く引き伸ばされたグリフの正確なオフセット値を計算する必要がありますが、何らかの理由で計算しません。 元の「ヒントなし」オフセットを使用するように変更する必要がありました。 変更されたバージョンもデモプログラムに含まれています。 グリフ曲線が取得されたら、アフィン変換を使用して圧縮し直します。 最も単純なケースでは、これで十分です。 カーニングテーブルには、かなり正確な値が含まれています。

そこで、David Turnerに話を戻します。X軸に沿ったヒントを無視して、Y軸に沿ったヒントのみを許可するオプションをautohinterに追加するのは理にかなっていますか? または、既存のヒントよりもはるかに簡単な別の1次元ヒントを作成できます。 ご覧のとおり、サブピクセルRGBラスタライズを使用したテキストは、Adobe Acrobat Readerと非常によく似ており、いずれの場合も、最新のLinuxシステムよりもはるかに優れています(この記事は2007年-およそTransl。に書かれています )。 これは、Linuxベースのシステムの普及と普及に役立つと考えています。

Windows APIの使用ははるかに複雑です。 GetGlyphOutline()関数は、整数ピクセルのオフセット値を返しますが、これは私たちにとっては無礼です。 ストレッチは保存されません。 GetCharABCWidthsFloat()のような関数もありますが、ヒント付きグリフの値を計算し、浮動小数点数が含まれているにもかかわらず実際には整数であるため、役に立たないのです。 そのため、正確なオフセットを取得する簡単な方法を見つけられませんでした。 その結果、2つのフォントを同時に使用する必要がありました。1つは高さ1024ピクセルで、もう1つは必要なサイズで、ヒントとストレッチアフィンマトリックスを使用していました。 私は何かを見逃しているかもしれないと認めますが、これをより正確に実装する方法については考えていません。 おそらく彼らは、Microsoft Wordの文書化されていない機能をいくつか使用していますが、これは競合という点で完全に不正です。 もちろん、これを完全に確信することはできませんが、状況から、MicrosoftはWYSIWYGドキュメントツールを開発するための十分なAPIを意図的に提供していないと思わせます。 これは典型的な独占政策であり、その結果、技術進歩の阻害につながります。

実際、さらに悪いことです。 特許取得済みのヒントは、「ストレッチ」マトリックスでは機能しません。 少なくとも、グリフを正しく処理するスケーリングファクターは1つも見つかりませんでした。 1:1スケールのみが正常に機能しましたが、その結果、スムージングなしで白黒のラスタライザーを使用せざるを得なかった同じ問題が発生しました。



気味が悪いね。 スケーリングを行うと、グリフがひどく破損します。 ここで、たとえば、斜体のTimes New Roman(16倍の水平ストレッチ):



それともそうです。 Arial(100倍の水平ストレッチ)-面白い汚れ しかし、読むことは不可能です。



FreeType autohinterがどんなストレッチに対しても正しく機能すると言っても意味がないと思います。

Microsoft APIは、エンジニアリング文化やグローバルなアイデアを一切持たない「ひざまずき」の不健康なランダムソリューションの集まりに過ぎないようです。 一般に、Microsoftソフトウェアは1つのハードコードされた方法でのみ使用できます。 右へのステップ、左へのステップ-そしてすべてがなくなっています。 これは彼らのビジネスには良いかもしれませんが、少なくとも公平ではありません。 このようなポリシーは、平等な競争の条件に違反し、その結果、市場の全体的な進歩を遅らせます。 独占禁止委員会は、Media PlayerまたはInternet Explorerをシステムから削除するというばかげた要件ではなく、この状況に注意を払う必要があります。

最終的に、値「16」はより小さな悪であり、ほとんどの場合に適していますが、それでもイタリックタイムズニューローマンでは機能しないことがわかりました。

デモプログラム


TrueTypeを使用するWindowsプログラムは次のとおりです。
www.antigrain.com/research/font_rasterization/truetype_test_02_ft.zip

そして、Windows APIを使用するバージョンは次のとおりです。
www.antigrain.com/research/font_rasterization/truetype_test_02_win.zip

FreeTypeのバージョンには、プログラムディレクトリに次のファイルが必要です:arial.ttf、ariali.ttf、georgia.ttf、georgiai.ttf、tahoma.ttf、times.ttf、timesi.ttf、verdana.ttf、verdanai.ttf。 これらは%WINDIR%\ Fontsフォルダーにあります。

コンパイルする場合は、 AGGバージョン2.4または2.5をダウンロードし、agg-2.4 \ research \ win32 \ trutype_lcd \ *。*のようなファイルを解凍します。 FreeTypeバージョンの場合、FreeTypeを自分でビルドする必要があり、場合によってはプロジェクトの設定を変更する必要があります。

AGGの例で使用されているものと同様の適切なメイクファイルを作成すると、プログラムをLinux / X11または別のシステム用にコンパイルすることもできます。

FreeTypeのバージョンとWinAPIのバージョンのテキストは、ヒントアルゴリズムが異なるために異なって見えます。



ここには多数の設定が表示されます。 まず、フォントを変更するだけでなく、カーニング、ヒント、サブピクセルRGBラスタライズのオン/オフを切り替えることができます。 さらに、画像を反転して、黒い背景に白いテキストを表示できます。

フォントスケールスライダーを使用すると、フォントサイズをスムーズに変更できます。 ご覧のとおり、ヒントがオンの場合、線はピクセルに関連付けられますが、テキストの幅は滑らかに変化し続けます。 間隔を変更することで、この効果をよりよく見ることができます。 ヒントなしで、テキストのレイアウトはどの縮尺でも完全に保持されますが、テキストはぼやけて見えます。 垂直のスナップ線-テキストの鮮明さと精度の間の最も合理的な妥協点。 私自身、キャラクターの形を維持しながら、垂直方向のヒントが品質を改善する方法にショックを受けています。

間隔、幅、および斜体のイミテーションスライダーは、コメントを必要としないと思います。 コンピュータグラフィックスに精通している人にとっては、これらが通常のアフィン変換であることは明らかです。 1つの事実のみに注目したいと思います。「白黒」モードと「サブピクセルRGBラスタライズ」モードでは、「イタリックシミュレーション」スライダーの動作が少し異なります。 これは、アークタンジェントを介して値を正しく処理するのが面倒だったためです。 いずれにせよ、これは重要ではありません。

私が特に誇りに思っている機能は「大胆な模倣」です。 次のように機能します。



別の簡単なトリックがあります。 AGGには、特定のポリゴンの等距離を計算できるconv_contourユーティリティがあります。 ただし、直接使用するとぼやけた結果になり、サインの形状も大きく変化します(ただし、これはグローやシャドウエフェクトに役立ちます)。



ぼやけは簡単に回避できます。 グリフをたとえば100倍または1000倍垂直に引き伸ばし、等距離ポリゴンを計算して圧縮します。 そのため、結果として、Y軸に沿った座標はほとんど変化せず、テキストは明確なままです。 デモプログラムにはfaux_weightクラスがあります。 繰り返しますが、無料の水平スケーリングがどれだけ多くの機会をもたらすかは驚くべきことです。 そして、驚くべきことではありませんが、ピクセルに垂直にスナップすると視覚的な結果が改善されます。

別の例(この自由が大好きです):



これはすべて同じジョージア州のヘッドセットですが、ソフトウェアのみが変換されています。 完全に読みやすく、鮮明で、同時に滑らかです(はい、私は同意します、彼女は手動カーニングで傷つけられないでしょう)。

または、Tahomaヘッドセットでも同じです。



ガンマ調整スライダーは、ガンマ補正を制御します(チャンネルごとに個別に実行されます)。 理論的には、「直接の色域」を元の色に適用し、シーンをレンダリングした後、「逆の色域」を適用する必要があります。 ただし、これらの例のテキストは常に白または黒であるため、最初の操作には意味がありません。

プライマリウェイトスライダーは、Steve Gibsonの説明に従ってエネルギー分布を制御します: www.grc.com/freeandclear.htm 。 一次体重のみを管理し、残りを適宜計算するだけで十分です。 プライマリウェイトを増やすことで、テキストをより明確にすることができますが、文字の周りに色付きのアウトラインが表示されます。 0.5までの値を使用するのは理にかなっています。値が大きいと、「グロー」の色が目立ちやすくなります。 私に関しては、Windows ClearTypeは、あまりにも目立つ色「グロー」も提供します。

このようなラスタライズは迅速に機能します


デモプログラムはかなり遅いです。 部分的にはベクター操作がオンザフライで実行されますが、主にそれ自体が非常に遅いWinAPI GetGlyphOutline()関数が原因です。 一方、このようなラスタ化は、ハードウェアアクセラレーションによるテキストのラスタ化と同じくらい高速です。 ただし、最初に、ヒント、正しいレイアウト、および明確なサブピクセル品質を維持しながら、任意に可変のテキストのラスタライズを加速することは、原則として簡単な作業ではないことに同意する必要があります。 任意の変換とは、遠近法や非線形変換など、本当に任意の変換を意味します。

ほとんどの場合、東アジア言語を使用している場合でも、水平テキストを処理する必要があります。 さらに、ほとんどのグリフは同じ公称サイズを使用します。 ここでは、キャッシュメカニズムが役立ちます。 3つのRGBチャンネルのサブピクセルモノクロマスクには3倍のメモリが必要ですが、同時に最大1/3ピクセルのテキスト配置精度が得られます。 ほとんどの場合、これは非常にうまく機能します。 理論的な「豪華な」ラスター化の場合を除き、グリフごとに2つの白黒マスクを使用して、1/6ピクセルの精度を得ることができます。 ソフトウェアアルファミキシングでも非常に高速に動作します。最新のIntelプロセッサまたはPPCではグリフあたり約2〜4ミリ秒です。 GPUを使用すると、適切なテクスチャをロードすると、これはさらに速くなります。 唯一の問題は、GPUがチャンネル間でアルファブレンディングを許可する必要があることです。これは、私が知る限り、可能だと思われます。 少なくとも、David Brownはプレゼンテーションでこれについて言及しています[8]。 しかし、このトピックに関する詳細情報(ピクセルシェーダーから6チャネル出力を取得する方法)を見つけることができなかったため、このトピックに関するリンクを提供していただければ幸いです。

参照資料


  1. Joel Spolsky、フォントスムージング、アンチエイリアス、およびサブピクセルレンダリング。
    www.joelonsoftware.com/items/2007/06/12.html
  2. スティーブギブソン、サブピクセルフォントレンダリングテクノロジー。
    www.grc.com/cleartype.htm
  3. マキシムシェマナレフ、Windows Longhornの内部ClearType。
    www.byte.com/documents/s=9553/byt1113241694002/0411_shemanarev.html
    (オンライン登録が必要です。)
  4. FontFocusホワイトペーパー、artofcode.com / fontfocus
  5. ジェフアトウッド、フォントレンダリング:ピクセルグリッドの尊重。
    www.codinghorror.com/blog/archives/000885.html
  6. Charles Poynton、ガンマに関するよくある質問。
    www.poynton.com/GammaFAQ.html
  7. Dave Shea、サブピクセルサファリ。
    mezzoblue.com/archives/2007/06/12/a_subpixel_s
  8. David Brown, Avalon Text. A PowerPoint presentation.
    download.microsoft.com/download/1/8/f/18f8cee2-0b64-41f2-893d-a6f2295b40c8/TW04007_WINHEC2004.ppt
  9. Brian Friesen, ZoomIn Program.
    www.csc.calpoly.edu/~bfriesen/software/zoomin.shtml
  10. David Turner and the others, FreeType font Library.
    freetype.org
  11. Jim Mathies, XP Style DPI Scaling.
    www.mathies.com/weblog/?p=908
  12. Long Zheng, Windows Vista DPI scaling: my Vista is bigger than your Vista
    www.istartedsomething.com/20061211/vista-dpi-scaling

PS:Webアーカイブの記事の最初の部分(写真付き)。Webアーカイブ内の記事の2番目の部分(写真付き)。

PPS:画面タイポグラフィのトピックに興味のある人のためのいくつかの興味深いリンク:
書体:
Windows 8の予算モニター上の 単純なフォントではありません
Windows OSの高DPI値
プログラマを保護するために

Source: https://habr.com/ru/post/J112400/


All Articles