このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。
昨日の考察を踏まえて、ピクセルを領域として考えてみよう。
領域と捉えた場合は、ピクセルは正方形の範囲となり、
左上のピクセルは、(0, 0) - (1, 1) の座標で表現される。
以前の場合と異なり、ピクセルの座標が点で定まらないので、
これに直接近傍法を適用するのは難しい。
そこで、範囲から代表となる点を選ぶことにしよう。
正方形の範囲から、それを代表する点を考える場合、
正方形の中央の点を使うのが自然な考え方だ。
そうすると、左上のピクセルの代表的な座標は、
(0, 0) - (1, 1) の中心である、(0.5, 0.5) と決められる。
実装を基準に考えてみよう。
プログラミング上では、画像を配列として扱うため、
先頭の要素番号(添字)は 0 となる。
つまり「要素番号」に 0.5 を足せば「座標」が求まるのだ。
その上で、従来のように座標変換を行うと、
元の画像上での「座標」が求まる。
最終的に、その「座標」を「要素番号」に戻してやれば、
最も近くにある元のピクセルが求まることになる。
ではやってみよう。
# BMP 読み込み。
my $src = read_bmp;
# 画像の幅と高さを取得。
my $scx = @{$src->[0]};
my $scy = @$src;
# 新しい画像の幅と高さを決める。
my $dcx = 105;
my $dcy = 90;
# 新しい画像のデータを準備する。
my $dest = [ map { [ (0) x $dcx ] } 1 .. $dcy ];
for (my $dy = 0; $dy < $dcy; ++$dy) {
for (my $dx = 0; $dx < $dcx; ++$dx) {
no integer;
# 新しい座標に対応する元の座標を求める。
# 要素番号に 0.5 を足せば座標が求まる。
#
# my $px = $dx + 0.5;
# my $py = $dy + 0.5;
#
# ピクセルを領域と考えた場合は、
# サイズに合った自然な変換式となる。
#
# my $sx = $px / $dcx * $scx;
# my $sy = $py / $dcy * $scy;
#
# 座標から 0.5 を引くと要素番号が求まる。
#
# $sx -= 0.5;
# $sy -= 0.5;
#
# 要素番号を四捨五入して最も近い位置を得る。
#
# $sx = int($sx + 0.5);
# $sy = int($sy + 0.5);
#
# 上の式をまとめると以下のようになる。
# 近傍検索のための四捨五入と、
# 座標⇔添字変換で 0.5 の加算と減算が相殺され、
# 意外に単純な計算式となるのだ。
my $sx = int(($dx + 0.5) / $dcx * $scx);
my $sy = int(($dy + 0.5) / $dcy * $scy);
$dest->[$dy][$dx] = $src->[$sy][$sx];
}
}
# BMP を書き出す。
write_bmp($dest, 24);
どうだろう、ピクセルの重み的には自然な拡大となってるはずだ。
参考に、アイコンの拡大も乗せておくが、
以前の近傍法と比較して、周辺の枠が
心なし太くなった気がするかもしれない。