C#画像処理

【C#】グローバル変換とローカル変換

画像を拡大縮小表示する場合は、.NET Frameworkのアフィン変換の機能を用いて表示するのが比較的簡単なのですが、そのアフィン変換にもグローバル変換ローカル変換というものがあります。

 

詳細はMSDNのページ

グローバル変換とローカル変換 - Windows Forms .NET Framework
Graphics オブジェクトによって描画されたすべての項目にグローバル変換が適用されるしくみと、特定の項目にローカル変換が適用されるしくみについて説明します。

 

にも書いてありますが、グローバル変換はGraphicsクラスのTransformプロパティにアフィン変換用の行列のMatrixオブジェクト(名前空間:System.Drawing.Drawing2D)を指定すれば、Grapgicsオブジェクトへ描画する画像や線は、そのMatrixオブジェクトに基づいて拡大縮小、移動表示されるので、個々の画像や線などをアフィン変換する必要がなく、簡単といえば簡単なのですが、画像は拡大したいけど、文字は拡大したくない場合などに不都合があります。

 

下図の左側の画像がフローバル変換を用いて描画した結果ですが、画像を拡大すると、文字は大きくなり、線幅も太くなってしまいます。

(ここでは右側の画像のように拡大しても線幅や文字の大きさが変わらないのが目標)

【C#】グローバル変換とローカル変換

 

それに対して、ローカル変換は画像や線に対して個々にアフィン変換を行い表示を行うのですが、実際にアフィン変換が出来るのはGraphicsPathのみで、画像に対するアフィン変換が用意されていません。

 

そこで、画像に対してもアフィン変換行列であるMatrixオブジェクトに基づいて、画像の拡大縮小を行うメソッドを作成しました。

private void DrawImageLocal(
    Graphics g, 
    System.Drawing.Drawing2D.Matrix mat,
    Bitmap bmp)
{
    if (bmp == null) return;

    // 描画元の領域
    var srcRect = new RectangleF(-0.5f, -0.5f, bmp.Width, bmp.Height);

    // 描画先の座標(描画元に合わせる、左上、右上、左下の順)
    var points = new PointF[]
    {
        new PointF(srcRect.Left, srcRect.Top),
        new PointF(srcRect.Right, srcRect.Top),
        new PointF(srcRect.Left, srcRect.Bottom),
    };
    // 描画先の座標をアフィン変換で求める(変換後の座標は上書きされる)
    mat.TransformPoints(points);

    // 描画
    g.DrawImage(
        bmp,
        points,
        srcRect,
        GraphicsUnit.Pixel
        );
}

ここでポイントとなるのが、描画元の左上の座標が(-0.5,-0.5)となっているのですが、これは一番左上の画素の中心が(0, 0)で、画素の左上の座標は(-0.5, -0.5)となるためで、詳細は以下のページを参照下さい。

 

【C#】画像の座標系
画像を描画するにはDrawImageメソッドを用いますが、DrawImageメソッドはいくつものオバーロードが定義されていますが、画像の拡大縮小を考慮すると、個人的には以下の定義をよく用います。 public void DrawImage(...

 

これらを使って作成したサンプルプログラムがこちら↓

 

動作イメージ

 

ダウンロード

Global_Local_Transform.zip

 

関連記事

【C#】画像の座標系
画像を描画するにはDrawImageメソッドを用いますが、DrawImageメソッドはいくつものオバーロードが定義されていますが、画像の拡大縮小を考慮すると、個人的には以下の定義をよく用います。 public void DrawImage(...
【C#】グローバル変換を使ったアフィン変換
.NETで画像や線などを描画する時はGraphicsオブジェクトに対して描画を行いますが、このGraphicsオブジェクトの座標系をアフィン変換する処理をグローバル変換と言います。 グローバル変換された Graphicsオブジェクトに対し描...
【C#.NET】マイクロソフト仕様のアフィン変換
.NETでは座標のアフィン変換用にMatrixクラス(名前空間:System.Drawing.Drawing2D)が用意されています。 しかしながら、やっかいな事に、私の思う普通のアフィン変換の行列の表現が行と列が逆(転置されている)だし、...
【C#】GraphicsPathの描画
GraphicsPathの特長の一つでもあるアフィン変換を駆使した描画をしてみたいと思います。 パスの描画は、パスをnewしてAddLineなどのメソッドで図形を描画し、DrawPath(輪郭の描画)やFillPath(塗りつぶした描画)で...

 

画像処理のためのC#テクニックへ戻る

コメント

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