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

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

 

詳細はMSDNのページ

https://msdn.microsoft.com/ja-jp/library/c499ats3(v=vs.110).aspx

 

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

 

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

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

 

それに対して、ローカル変換は画像や線に対して個々にアフィン変換を行い表示を行うのですが、実際にアフィン変換が出来るのは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#】画像の座標系

 

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

 

動作イメージ

 

ダウンロード

Global_Local_Transform.zip

 

関連記事

【C#】画像の座標系

【C#】グローバル変換を使ったアフィン変換

【C#.NET】マイクロソフト仕様のアフィン変換

【C#】GraphicsPathの描画

 

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

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください