[osask 7189] Re: picture0+ico

こんにちは, I.Tak.です。[osask 7187]に返信です。

Akira Ouchi wrote:
>>フルカラー(b_type=4)さえできてしまえば減色ルーチンが使えますが
>>……誤差拡散ルーチンの説明はどこにも書いてませんでしたか(^^;
>>使います?
> 
> うーん、MLとかにあるのかなぁ?よくわからないのでI.Tak.さんにお任せしま
> す。

どこにも書いてないはずですので, この機会に説明してしまおうと思います。

誤差拡散について:
減色すると元の画像と同じ色が使えるとは限らないので,
同じ色が無い場合は暗い色を代わりに使う。生じた誤差は,
隣りのピクセルをその分明るくすることでごまかす。
というものです。

誤差拡散ルーチン仕様:

extern void gosakaku16(int delta, int *deltabuffer, int width, const int
*source, short *dest);
extern void gosakaku6(int delta, int *deltabuffer, int width, const int
*source, char *dest);
extern void gosakaku4(int delta, int *deltabuffer, int width, const int
*source, char *dest);
extern void gosakaku3(int delta, int *deltabuffer, int width, const int
*source, char *dest);

減色で発生した誤差を右と下へ半分ずつ伝播するタイプの
誤差拡散ルーチン。一行だけ減色する。

delta = 左からの繰り越し誤差。
deltabuffer = 上の行からの繰り越し誤差。
source から width 個の32bpp (RGB888) ピクセルを読み,
16bpp (RGB565), 6bpp (RGB222), 4bpp (IRGB1111), 3bpp (RGB111)
に減色して dest に書く。
発生した誤差は deltabuffer に書き込まれるので, 通常は初期化以外に
deltabuffer をいじる必要はない。

deltabuffer, source, dest ともにwidth個の要素が必要。

典型的な呼び方:
/****************************************/
int i, width = ほげ, height = ほげ;
int *deltabuffer = malloc(width * 4), *source = 画像;
short *dest = malloc(ほげ);

for (i = 0; i < width; i++)
    deltabuffer[i] = 0;        /* 誤差0に初期化 */

for (i = 0; i < height; i++) { /* 上から下までループ */
    gosakaku16(0, deltabuffer, width, source, dest);
    dest += width;             /* 次の行へ */
    source += width;           /* 次の行へ */
}
/****************************************/

ここで左からの誤差 delta = 0 としているのは, 画像の左端から右端まで
一気に減色しているため。JPEGのようにブロック単位で処理する場合は
左のブロックから誤差を持って来る必要がある。


こんな感じです。宣言がjpeg.cに書いてあるのと微妙に違いますが,
アセンブリ言語はそのへんいい加減なので気にしないでください;-)

I.Tak.<t40370@mail.ecc.u-tokyo.ac.jp>

ML番号でジャンプ
ML単語検索