画像を描画するにはDrawImageメソッドを用いますが、DrawImageメソッドはいくつものオバーロードが定義されていますが、画像の拡大縮小を考慮すると、個人的には以下の定義をよく用います。
public void DrawImage(
Image image,
Rectangle destRect,
int srcX,
int srcY,
int srcWidth,
int srcHeight,
GraphicsUnit srcUnit
)
public void DrawImage(
Image image,
Rectangle destRect,
float srcX,
float srcY,
float srcWidth,
float srcHeight,
GraphicsUnit srcUnit
)
この時の座標系は下図の用になり、元の画像に対して、画像の描画先(destRect)を大きくすると画像の拡大となり、描画先を小さくすると画像の縮小となります。
しかしながら、以下のように単純に画像の拡大のプログラムを実行すると、
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
var srcImage = new Bitmap("sample.bmp");
Graphics g = e.Graphics;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
g.DrawImage(
srcImage,
new Rectangle(0, 0, srcImage.Width * 50, srcImage.Height * 50),
0,
0,
srcImage.Width,
srcImage.Height,
GraphicsUnit.Pixel
);
}
このように画素の半分だけ画像が左上にずれて表示されてしまいます。
これは、元の画像の座標系の原点が画素の中心部分にあるためで、このようになります。
このズレを無くすには、やり方は2つ
●PixelOffsetModeを指定する方法
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
var srcImage = new Bitmap("sample.bmp");
Graphics g = e.Graphics;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
g.DrawImage(
srcImage,
new Rectangle(0, 0, srcImage.Width * 50, srcImage.Height * 50),
0,
0,
srcImage.Width,
srcImage.Height,
GraphicsUnit.Pixel
);
}
●元の画像の座標を0.5画素ズラす方法
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
var srcImage = new Bitmap("sample.bmp");
Graphics g = e.Graphics;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
g.DrawImage(
srcImage,
new Rectangle(0, 0, srcImage.Width * 50, srcImage.Height * 50),
-0.5f,
-0.5f,
srcImage.Width,
srcImage.Height,
GraphicsUnit.Pixel
);
}
このようにすると、表示のズレが無くなります。
単に画像を拡大/縮小表示するだけなら、PixelOffsetModeを指定した方が簡単だと思いますが、アフィン変換などの座標変換を伴う場合は、元の画像の座標を-0.5分だけ図ずらしたやり方の方が良いかと思います。
←画像処理のためのC#へ戻る