2006 年 2 月 25 日 21 時 18 分

近傍法による画像の縮小


このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。


[写真] [写真]


等間隔で間引きを行う方法は、
整数分の 1 のサイズにした変更できなかった。
任意のサイズに縮小するには、
間引きの方法を考える必要がある。

その代表的な手法に、近傍法がある。
これは、新しい画像のピクセルの位置に対応する、
元の画像のピクセル位置を計算し、
そのピクセルを利用するという方法である。

計算は、「表現ビット数の削減による減色」でやった、
範囲(区間)の計算と同じように考えるといい。

例えば、元の画像が 120 ピクセルの幅とし、
縮小後の画像が 100 ピクセルの幅とすると、
元の横方向は、0 から 119 までの区間と考え、
縮小後の横方向を 0 から 99 までの区間と考えられる。

なので、0 ~ 99 の範囲の値を、
0 ~ 119 の範囲に変換する式を使えば
縮小後の位置から元の位置が計算できる。
$original = int($shrunken * 119 / 99 + 0.5);


# BMP 読み込み。
my $data = read_bmp;

# 画像の高さと幅を取得。
my $scy = @$data;
my $scx = @{$data->[0]};

# 新しい画像の高さと幅を決める。
my $dcy = 75;
my $dcx = 100;

# 近い位置のピクセルを
# 画素を左上に持ってくる。
for (my $dy = 0; $dy < $dcy; ++$dy) {
    for (my $dx = 0; $dx < $dcx; ++$dx) {

        no integer;

        # 新しい座標に対応する元の座標を求める。
        my $sx = int($dx / ($dcx - 1) * ($scx - 1) + 0.5);
        my $sy = int($dy / ($dcy - 1) * ($scy - 1) + 0.5);

        $data->[$dy][$dx] = $data->[$sy][$sx];
    }
}

# データの幅と高さを調整する。
$#$data = $dcy - 1;
$#$_ = $dcx - 1 foreach @$data;

# BMP を書き出す。
write_bmp($data, 24);

今日は、Windows のアイコンをサンプルとしてみよう。
Mixi の仕様を考え、元の画像は 120 x 90 としてある。

絵の部分と文字の部分は、画像としての特性が違うので、
昨日の考察どおり、アイコンは品質を保っているが、
文字は重要な部分が欠落して、非常に読みにくいことが分かる。



Copyright (c) 1994-2007 Project Loafer. All rights reserved.