雑な k|m の生態について ph.19 2002-11-03

静止画にアンチエイリアスを施すコード anti_alias() に関する雑記

aa01.cpp は静止画像にアンチエイリアスを施すルーチンです。しかしちょっと問題もあるんですよね。この問題はアンチエイリアスを実装するアルゴリズムに強く依存する問題であり,このようなリソースを残す意味は多分に希薄かと。でも書いてしまったものは仕方ありません。

aa01.cpp 使用方法

使用方法はあまり難しいものではなく,aa01.h を見れば分かるように,実際に公開されている API は anti_alias() ただ 1 つです。

int anti_alias(
                 int   threshold,
        unsigned char *dst,
        unsigned char *src,
                 int   bpl,
                 int   height,
                 int   depth );
threshold
anti_alias() は元画像から輝度情報を抜き出し,任意のピクセルと隣のピクセルとの輝度を比較してアンチエイリアスを施すべきかどうかを決定します。threshold は,どれくらい輝度が離れていればアンチエイリアスを施すべきかという閾値を 0〜255 で指定します。
dst
アンチエイリアス後の画像を格納する場所を示します。
src
アンチエイリアス前の画像を保持している場所を示します。
dstsrc は,例えば Win32 API の ::CreateDIBSection() で割り当てられるメモリ領域によく適合します。malloc() などで独自に領域を割り当てる場合,必ず横 1 ラインのサイズは“ 4 の倍数”バイトでなければなりません。画素深度 24 ビットで横 3 ドットの画像の場合,横 1 ラインに必要なサイズは 9 バイトですが,あえて 12 バイトを割り当て 4 の倍数に揃えます。
dstsrc は同じサイズである必要があります。anti_alias() は,それぞれの BPL および高さが同じであると仮定します。
dstsrc が同じ場所を指している場合,アンチエイリアスは正常には行われない可能性があります。
bpl
画像の BPL を入力します。4 の倍数であるはずです。
height
画像の高さを入力します。
depth
画像の画素深度を入力します。24 もしくは 32 以外の値が入力された場合,アンチエイリアスは正常に行われない可能性があります。

anti_alias() を使う前に,もしかしたら aa01.cpp を書き換える必要があるかもしれません。

static
unsigned char *get_luminances( ... ) {

  ...
  // ここ
  unsigned char *luminances = (unsigned char *)malloc( width * height );

  ...
static
void release_luminances(unsigned char *luminances) {
  free(luminances); // ここ
}

malloc() および free() を用いない場合,適切な関数に置き換えます。

このアルゴリズムの問題点

OK,もしあなたが今までにアンチエイリアスのコードを見た事も書いた事も無いならば,今日はそれなりに良さげなコードを見た最初の日です。そうではなくこれまでに何度か書いた事のある人ならば,即刻退去願います。恥ずかしいんで。

このコードでアンチエイリアスを行うと,次のような問題が発生します。このように二又に分かれた線分にアンチエイリアスを施すと,

data01.png 二又に分かれた線分

こんな結果が得られます。

data02.png - アンチエイリアス後

このうち,赤で囲んだ部分で・・

data03.png - 気になる部分を赤で示しています

なんだか非理論的な変化をしているのが気になって仕方ありません。これは anti_alias() が次のように処理を行うからです。まず anti_alias() は次のような傾きのある線分に気づきます。

data04.png - 右下に伸びる線分

そこで,次のようにグラデーションを描画します。

data05.png - 右下に伸びる線分にアンチエイリアス処理

次に,下のような線分にも気づきます。

data06.png - 右上に伸びる線分

このようなグラデーションを描画します。

data07.png - 右上に伸びる線分にアンチエイリアス処理

これを合成する事で最初の図のような奇妙なグラデーションが生成されるわけです。これを解決するには色々と方法が考えられますが,どの方法を採用するかは検討中という事で。


written by kuri|minima. (warai / tkuri@fat.coara.or.jp