C#

【C#】画像の座標系

画像を描画するには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)を大きくすると画像の拡大となり、描画先を小さくすると画像の縮小となります。

 

C# 画像の座標系

 

しかしながら、以下のように単純に画像の拡大のプログラムを実行すると、

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
     );
}

 

このように画素の半分だけ画像が左上にずれて表示されてしまいます。

C# 画像の座標系

 

これは、元の画像の座標系の原点が画素の中心部分にあるためで、このようになります。

C# 画像の座標系

 

このズレを無くすには、やり方は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
        );
}

このようにすると、表示のズレが無くなります。

C# 画像の座標系

 

単に画像を拡大/縮小表示するだけなら、PixelOffsetModeを指定した方が簡単だと思いますが、アフィン変換などの座標変換を伴う場合は、元の画像の座標を-0.5分だけ図ずらしたやり方の方が良いかと思います。

 

画像処理のためのC#へ戻る

コメント

タイトルとURLをコピーしました