日記緑ログ

2006/10/01 ~ 2006/10/31

目次

戻る

Blog

Sepia for 48bit Bitmap Filter

[Create: 2006/10/01 20:06] [LastUpdate: 2006/10/01 20:07]

過去ログ置き場の48bit Bitmap Filterを更新し、セピアフィルタを同梱しました。

ついでに恥ずかしいバグを修正。

セピアは実験的にやって見た感じで設定がありません。

時代はいつまでINIファイルなのか

[Create: 2006/10/03 19:57] [LastUpdate: 2006/10/03 20:09]

wxConfig で設定保存

構成ファイルの読み書き

あたりが関連していますが読む必要はこれっぽっちもありません(^^;

.NET時代はXMLだというMSの主張はばっさり無視し、INIのお話。

XMLによる設定の保存が今ひとつ進まないのはいくつか理由が考えられますな。

ま ずはライブラリ。.net frameworkやJavaなら最初からXMLでウハウハなのですがいまだ現役C++君だとかCさんにはつらい。COMでMSXMLというもの嫌だし (ただのCOM嫌いレジストリ嫌いかもしれないが)、自分で実装するにも大変(難しいではなく面倒)だしといったところ。libxml2とかXerces も確かにあるしできもいいのだが結構でかいので勇気がいる(libxml2-2.6.26のlibxml2.dllは939KB、xerces- c_2_7.dllは2.25MBある。今ならたいした事は無いさと思うがやっぱり使うのは勇気がいる)。

さらに言うとXMLはオーバースペックだとも思える。確かにある程度の規模になってくれば利いてくるが特に属性などそんなに使わないのではないか。階層構造もそれほど必要ではないのではないか(いや便利だけどさ)。

加えて扱いの煩雑さもある。DOMのほうが楽だと思うがこれが結構面倒なのだ。Documentから下のElementをとってさらに子のElementをとってその上でElementをとるとそれが目的のTextElementであったという具合なので長くなる。

一 応速度面にも触れるがレジストリ(固定長レコードのような典型的なデータベース)よりは速度が劣化すると思うが、それほど遅くない。DOMならオンメモリ でやっちまえるからParseした後は軽快に動作するはずだ。ただオブジェクト間の構造の複雑さに伴って速度の劣化はあるが。

この煩雑さが実装を厄介にする。C、C++ではポインタの嵐になるわけだが注意深く実装しないとメモリリークでさようならである。

というわけで軽量でまあそこそこ十分なINIがまだまだ使われているわけだ。Windowsなら「ああ面倒だ。レジストリのハンドルを開くのも面倒だ。WritePrivateProfileStringで一発じゃね?」と、こうなってしまう。

その流れに関連してかせずかINIを使うためのライブラリを実装することも多い。

以前INIファイルでちらっと紹介したiniParser: stand-alone ini Parser library in ANSI Cも その一派でこういったものがもうそこら中にある。私もDelphiの(VCLの)TIniFileに魅せられた者だからインターフェイスがそっくりなもの をC++でSTLをごりごり使って実装した。実際便利である。templateでコンテナを自在にウハウハとも思ったのだがVCLのヘルプを参考にして似 たようなクラスの継承関係にしておいたためvirtualがついてまわってままならなかった。TStreamはiostreamがあるので余裕である。た だこれは不毛な気がしてやめてある。日付関連も決め手が無いので先送りしてある。

このINIは人気者らしくcodeprojectや sourceforgeにもよくある。ためしにいくつか落としてソースを見て見たがC++でSTL非依存でやるとかSTLつかうとかMFCだとかC#だと かJavaだとかCだとか一杯一杯だ。C#やJavaでは普段は素直にXMLを使えといいたいが現実は厳しいようだ。

ただし中には結構がっかりするものもある。紹介はしないがなぜかグローバル変数を使ってファイルハンドルをおいてみるとか奇妙なものもあった。

INIにはINIのINIがある。

[Create: 2006/10/03 20:11] [LastUpdate: 2006/10/03 20:25]

wxConfig で設定保存

構成ファイルの読み書き

INIファイル

あたりが関連していますが読む必要はこれっぽっちもありません(^^;

codeprojectやsourceforgeにもINIのなにがしかは沢山あるようでちょっとみてはがっかりを繰り返しております。

VCLに魅せられてTIniFileしかないだろ。と思いつつC++・STLで適当にでっち上げました。Windows APIとあわせて適当にやりましたがそれはそれとします。

で、作って使っていて思うのですがこのインターフェイスは実に前時代的です。iniParserもその通りですし、wxConfigのSetPathってなにさとか。

XMLのDOMのように

CIniFile* iniFile = new CIniFile("inifile.ini");

CIniSection* section = iniFile->GetSection("abc");

section->ReadInteger("def");

ぐらいにすると実に現代的で格好いい。が、私は面倒なんでTIniFileっぽいのが楽チン楽チン。と思ってしまう。駄目駄目。

# プログラマ's 研究所のソースライブラリにあるregfileはこれに近い。

FreeType2 のキャッシュを使おう。

[Create: 2006/10/06 18:14] [LastUpdate: 2006/10/06 19:46]

ずいぶん前に少しだけ触れてずっとほったらかしのFreeTypeを使った文字表示についてのその後。

縦書きの本格対応は後回しとしてキャッシュぐらいは真面目にやったほうが何かといいだろうということでそれについて少し触れておきます。

以前はドキュメントを読むことすら面倒だったのでstd::mapでごまかしておきましたが少しだけドキュメントに目を通すとなんとなしにできそうな予感がしたのでやってみました。

以下が初期化部分。

FT_Library freetype_library;
FT_Face freetype_face;
FTC_Manager cache_man;
FTC_ImageCache image_cache;
FTC_ImageTypeRec font_type;

FT_Init_FreeType(&freetype_library);
FT_New_Face(freetype_library, "msgothic.ttc", 0, &freetype_face);
FT_Set_Char_Size(freetype_face, 0, 96*64, 96, 96);
FTC_Manager_New(freetype_library, 0, 0, /*バッファの適当な大きさ*/, face_requester, freetype_face, &cache_man);
font_type.face_id = (FTC_FaceID) 1;
font_type.width = (short) 96;
font_type.height = (short) 96;
font_type.flags = FT_LOAD_RENDER;
FTC_ImageCache_New(cache_man, &image_cache);

FTC_Manager_Newのバッファの大きさには0を渡せば規定値を使うということですので今回はそれで。

サンプルのを流用していますのでそのあたりはご勘弁いただくとしてface_requesterはコールバックされる関数で以下のように定義。

FT_Error face_requester(FTC_FaceID face_id,
 FT_Library library,
 FT_Pointer request_data,
 FT_Face* aface )
{
    // request_dataにfreetype_faceを渡してもらっているので
    // そのまま返してやるがここでFT_New_Faceしてもよい。
    *aface = (FT_Face)request_data;

    return 0;
}

当然のようにもっと違うフェイスを使う場合にはもうちょっと考えて実装するべきでしょうね。

実際に文字を描き描きするには

FT_Glyph glyph;
FT_BitmapGlyph glyph_bitmap;
FT_UInt glyph_index = FT_Get_Char_Index(freetype_face, /*文字コード*/);
FTC_ImageCache_Lookup(image_cache,&font_type,glyph_index,&glyph,NULL);
glyph_bitmap = (FT_BitmapGlyph)glyph;
// glyph_bitmapのDraw処理

つまりはFTC_ImageCache_LookupをFT_Load_Glyphのかわりに使えと。

bitmapにキャストしているのは(できるのは)font_type.flagsにFT_LOAD_RENDERを指定しているから。ここでFT_LOAD_DEFAULTとかしてやってアウトラインデータをキャッシュすると空しい結果になりそう。

解放処理は

FTC_Manager_Done(cache_man);
FT_Done_FreeType(freetype_library);

でおしまい。FT_Done_Faceは必要なし。

FTC_CMapCacheも同様に使えるようでそれでキャッシュキャッシュでよかよかとなる様子。

適当に計測した結果

・測定方法

 AからZまでを1回目A、2回目B、3回目C、として5万回繰り返しFTC_ImageCache_Lookup、あるいはFT_Load_Glyphを呼び出す。

・開始から終了までをtimeGetTimeで適当に計測する。

結果

・FTC_ImageCache_Lookup

 1回目 27~30msぐらい

 2回目 24msぐらい

・FT_Load_Glyph

 9500~10000msぐらい

ここまで違えば効果は歴然といったところでしょう。ただしこの測定方法だとキャッシュするとあまりにも有利になるわけで(何しろA-Zまでしかないのだからすべてキャッシュされてしまうのだ)、日本語なんかだと実際の差はこれほどは開かないと思います。

参 考までにstd::mapで(以前使っていた方法だがまったく推奨できない)同様に計測してみました。この場合だと FTC_ImageCache_Lookupとほぼ同じでした。ただし手抜きをしている部分が多分にあります。さらにFreeType2ではハッシュを 使っていますのでもっとまともな状態だとツリーな実装との差は開くと思われます。

こんな具合で。

続・フォントのアンチエイリアス

[Create: 2006/10/07 11:37] [LastUpdate: 2006/10/07 11:50]

FreeType2とWindowsのレンダリングの例

以前フォントのアンチエイリアスでGDIとFreeType2のレンダリングについての比較を少しだけした。今回は続きである。

なお前回とはFreeTypeのバージョンが異なりFreeType 2.2.1を使った。差は無いと思うが一応情報だけ伝えておく。

早速だが画像を見ていただく。上から

FreeType2 AutoHinting有

FreeType2 AutoHinting無(通常)

CreateFontでアンチエイリアスをONにしたものをTextOut

GetGlyphOutlineでGGO_GRAY4_BITMAPを指定したもの

GetGlyphOutlineでGGO_GRAY8_BITMAPを指定したもの

CreateFontでアンチエイリアスをONにしたものをTextOut(XP)

一番下以外はWindows 2000 SP4の結果である。FreeTypeには影響は無いがGetGlyphOutlineに変化があるかもしれない。

判 断はお任せするとして2000とXPでレンダリングが違うのは本当のようだ。またWindows GDI標準のTextOutのアンチエイリアス処理はGetGlyphOutlineでGGO_GRAY4_BITMAPを指定したものと階調は大体同じ 程度のようだ。ただ内部処理は共通ではないようにみえる。

XPのものだが2000のものよりほっそりしている。ClearTypeと同時に手を入れられたようだ。

文字アンチエイリアシング調整

[Create: 2006/10/14 16:08] [LastUpdate: 2006/10/14 17:13]

アルファ値によるアンチエイリアス調節

アンチエイリアスでぼけるとかぼけるとか太くなるとかいう不満がつのることがあると思います。

普通のアンチエイリアスはアルファ値をとって

BYTE rs = GetRValue(color);
BYTE gs = GetGValue(color);
BYTE bs = GetBValue(color);

BYTE rd = GetRValue(target);
BYTE gd = GetGValue(target);
BYTE bd = GetBValue(target);

rd = (rd * (255 - alpha) + rs * alpha) / 255;
gd = (gd * (255 - alpha) + gs * alpha) / 255;
bd = (bd * (255 - alpha) + bs * alpha) / 255;
return RGB(rd, gd, bd);

のようにすると思います。まあ正統派ですね。除算がとか乗算がとかそういった細かい部分は捨て置いてこんな具合になるでしょう。

アンチエイリアスでボケボケというのは中間色が多すぎるというものがあると思いますがコントラストをばばーんと上げてしまえばぼけは取れてきます。逆にジャギーは目立つわけですからそのあたりは工夫する必要があるでしょう。

以下のようにテーブル引きするといいかもしれません。

BYTE rs = GetRValue(color);
BYTE gs = GetGValue(color);
BYTE bs = GetBValue(color);

BYTE rd = GetRValue(target);
BYTE gd = GetGValue(target);
BYTE bd = GetBValue(target);

BYTE newAlpha = table[alpha];

rd = (rd * (255 - newAlpha) + rs * newAlpha) / 255;
gd = (gd * (255 - newAlpha) + gs * newAlpha) / 255;
bd = (bd * (255 - newAlpha) + bs * newAlpha) / 255;
return RGB(rd, gd, bd);

テーブルは例えば

for(i = 0;i < 255;++i){
    col = i;
    if(col < 127){
        col -= contrast;
        if(col < 0) col = 0;
    }else{
        col += contrast;
        if(col > 255) col = 255;
    }
    table[i] = col;
}

の ような形で作成できます。ただこの計算だと中間値を均等に明暗に分けているだけですから0や255のようなキワの値の差べたっと無くなるだけでその他の中 間値は均等に増え、滑らかさが失われるだけですしジャギーがすぐに目立ち始めます。ですから0付近と255付近はなだらかに、中間は急峻に変化させてやる 必要があるはずです。

こういうのは何っていうんでしょうか。

ともかくそれっぽいものをこしらえておきました。

int i;
int col;
double tmp, p = (1 + (c / 10.0));
for(i = 0;i < 255;++i){
    tmp = ((i / 255.0) - 0.5) * 2;
    if(tmp < 0){
        tmp = pow(1.0+tmp, p)-1.0;
    }else{
        tmp = 1.0-pow(1.0-tmp, p);
    }
    col = (int)((tmp / 2 + 0.5) * 255.0);
    table[i] = col;
}

ま、深い突っ込みは無しとして、あと考えられるのはガンマ補正のような考え方でしょうか(といっても上記のものは近いが)。

画像は上がGetGlyphOutlineで取ったやつそのまま。真中はc=10、下はc=20のもの。下にいくほどほっそりして見えるのではないかと思います。

テキスト画像化バッチ処理

[Create: 2006/10/17 20:37] [LastUpdate: 2006/10/17 20:43]

バッチ出力もどきプログラムサンプル

バッチ処理でテキストを適当に組んで画像出力するようなものって面白そうじゃないか?

とある日思いました。

いまだできていません。

ぬあー

[Create: 2006/10/23 20:57] [LastUpdate: 2006/10/23 21:01]

FreeTypeはしばらくお預けします。

だってさFontAvenue(NEC)のさポップB、隷書M、勘亭流UB(これらはダイナラブからのライセンスを受けたもの)以外の本命たちが軒並みまともにレンダリングされないだもん。

ダイナフォントも変だというもあるけどFAも猛烈に変なのでちと困る(どちらも変は変だが)。

かといってFreeTypeの密林を歩く気力も実力も持ち合わせていないのでごめんなさいしておきますよ。

わからんけれどLinux系とかBSDとかあたりのXでは軒並みアウトなんじゃないですかね(Vine Linuxでちょっと試したけれど案の定変)。MACとかBeOSとかあっちのほうではどうなんでしょうかねえ。

新米新米

[Create: 2006/10/26 20:35] [LastUpdate: 2006/10/26 20:39]

新米を食べました。いや色が真っ白で驚きました。

と、これだけで終わるのもいいかもしれないなと思う。たまにはね。

FontAvenueとFreeType

[Create: 2006/10/31 19:17] [LastUpdate: 2006/10/31 19:40]

バイトコードインタプリタをONにするとまともっぽい文字になる。ヒンティングを無効にしたり、オートヒンティングを使うと化ける。

FAは元グリフが変な形状(太さが無い縦線とか)なのでヒンティングというか、変な動きで形作ってるっぽい。

よかったよかった。

ダ イナフォントはいいとして一部で話題のSun-Extも変(Sun-ExtB)。どうなるかといえば0x80未満ぐらいの英数字の幅が高さと同じになる (いわゆる全角幅になる)。それは幅といっても空白が半分なのです。まあTrueTypeフォントはMacとWindowsでも描画結果が違うわけでこの 程度ではまったく驚きませんよ。

条件が今ひとつ分かりませんがメモリリークすることがあります。三つしか試していませんがどれも邦字のOpenTypeフォント。

試したのはFreeType 2.2.1。

まあこれはいずれ直してもらえるでしょうから放置で(報告ぐらいするべきかもしれない)。

いやFreeTypeはお預けするって言いながらバンバン向こうに置いてたりしますけどそれはあれですよ。あれ。

ちなみにリンクをむやみにしないのは後で整合を取るのが面倒そうだから。

それではさらば。