画像の拡大縮小のアルゴリズムについてのメモ
画面をsrcと称し、拡大縮小される画像をdestと称す。
※なんかさー。Windowsプログラミングの作法じゃそんな風になってるみたいなんだけど、よく知らないんだよね。俺、モグリだから。fooとかbarとかhogeとかfugaみたいなもん?
destを拡大縮小(回転はしないとする)して、srcに貼り付けると言う動作。
ネックになるのは、拡大と縮小でどちらでも同じ結果になるようなアルゴリズムを考えないといけないということ。
srcの任意の座標に対し、それに対応するdestの座標の範囲が決まり、それらの平均の色を取得するのが基本のアルゴリズム。
struct PIXEL { int r; int g; int b; int count; }; PIXEL canvas[800][600]; PIXEL zero_pix; zero_pix.r = 0; zero_pix.g = 0; zero_pix.b = 0; zero_pix.count = 0; PIXEL dot; int sx, sy; int dx, dy; int dx1, dy1; int dx2, dy2; int add; // キャンバスを初期化 for ( sx=0; sx<800; sx++ ) { for ( sy=0; sy<600; sy++ ) { canvas[sx][sy] = zero_pix; } } // キャンバスを作成 for ( sx=0; sx<src_width; sx++ ) { dx1 = linear(0, src_width, sx, lx, rx); dx2 = linear(0, src_width, sx+1, lx, rx)-1; if ( dx2 > dx1 ) { } else { dx2 = dx1+1; } for ( sy=0; sy<src_height; sy++ ) { dy1 = linear(0, src_height, sy, ty, by); dy2 = linear(0, src_height, sy+1, ty, by)-1; if ( dy2 > dy1 ) { } else { dy2 = dy1+1; } dot = canvas[sx][sy]; for ( dx=dx1; dx<dx2; dx++ ) { if ( dx<0 ) continue; if ( dx>dest_width-1 ) continue; for ( dy=dy1; dy<dy2; dy++ ) { if ( dy<0 ) continue; if ( dy>dest_height-1 ) continue; add = (dest_height-dy-1)*dest_line+dx*3; // destの(dx, dy)を、srcの(sx, sy)の要素とする。 dot.r += int(dest[add+2]); dot.g += int(dest[add+1]); dot.b += int(dest[add+0]); dot.count += 1; } } canvas[sx][sy] = dot; } } // キャンバスを描画 for ( sx=0; sx<src_width; sx++ ) { for ( sy=0; sy<src_height; sy++ ) { dot = canvas[sx][sy]; if ( dot.count==0 ) continue; add = (src_height-sy-1)*src_line+sx*3; src[add+2] = unsigned char(dot.r / dot.count); src[add+1] = unsigned char(dot.g / dot.count); src[add+0] = unsigned char(dot.b / dot.count); } }