ワールド変換により画像を平行移動、拡大、縮小、回転して表示する補足:画像の表示方法が分からないという方は、まず「画像ファイルを表示する」をご覧ください。 「画像を拡大、縮小して表示する」、「画像を傾けて表示する」にて画像を拡大、縮小、回転して表示する方法を紹介しましたが、ここでは「ワールド変換行列」を使う方法を紹介します。 ワールド変換行列はMatrixオブジェクトで表わされ、Matrixオブジェクトには2x2の線形変換のための行列と、1x2の平行移動のための行列が組み合わさった、3x3のアフィン行列が格納されています(詳しくはヘルプの「変換の行列表現」をご覧ください)。あるGraphicsオブジェクトで描画されるすべての画像や図形に適用する変換(グローバル変換)のためのMatrixオブジェクトは、GraphicsオブジェクトのTransformプロパティで取得、設定が出来ます。 なにやら難しいことになってきましたが、平行移動、スケーリング、回転に関しては簡単に実現する方法が用意されていますので、ここではそれらを使うことにします。 あるGraphicsオブジェクトのワールド変換に平行移動を適用するにはGraphics.TranslateTransformメソッドを、スケーリングを適用するにはGraphics.ScaleTransformメソッドを、回転を適用するにはGraphics.RotateTransformメソッドをそれぞれ使用します。 次にこれらの変換を利用して画像を描画する例を示します。 [VB.NET] 'PictureBox1のGraphicsオブジェクトを取得 Dim g As Graphics = PictureBox1.CreateGraphics() '画像を読み込む Dim img As Image = Image.FromFile("test.gif") '普通に画像を描画 g.DrawImage(img, New Rectangle(0, 0, img.Width, img.Height)) 'ワールド変換行列を単位行列にリセット g.ResetTransform() 'ワールド変換行列を下に平行移動する g.TranslateTransform(0, img.Height + 10) '画像を描画 g.DrawImage(img, New Rectangle(0, 0, img.Width, img.Height)) 'ワールド変換行列を単位行列にリセット g.ResetTransform() 'ワールド変換行列にスケーリング操作を適用し、2倍に拡大する g.ScaleTransform(2.0F, 2.0F) '画像を描画 g.DrawImage(img, New Rectangle(img.Width, 0, img.Width, img.Height)) 'ワールド変換行列を単位行列にリセット g.ResetTransform() 'ワールド変換行列を45度回転する g.RotateTransform(45.0F) '画像を描画 g.DrawImage(img, New Rectangle(img.Width, img.Height, img.Width, img.Height)) 'リソースを開放する img.Dispose() g.Dispose() [C#] //PictureBox1のGraphicsオブジェクトを取得 Graphics g = PictureBox1.CreateGraphics(); //画像を読み込む Image img = Image.FromFile("test.gif"); //普通に画像を描画 g.DrawImage(img, new Rectangle(0, 0, img.Width, img.Height)); //ワールド変換行列を単位行列にリセット g.ResetTransform(); //ワールド変換行列を下に平行移動する g.TranslateTransform(0, img.Height + 10); //画像を描画 g.DrawImage(img, new Rectangle(0, 0, img.Width, img.Height)); //ワールド変換行列を単位行列にリセット g.ResetTransform(); //ワールド変換行列にスケーリング操作を適用し、2倍に拡大する g.ScaleTransform(2F, 2F); //画像を描画 g.DrawImage(img, new Rectangle(img.Width, 0, img.Width, img.Height)); //ワールド変換行列を単位行列にリセット g.ResetTransform(); //ワールド変換行列を45度回転する g.RotateTransform(45F); //画像を描画 g.DrawImage(img, new Rectangle(img.Width, img.Height, img.Width, img.Height)); //リソースを開放する img.Dispose(); g.Dispose();
画像を拡大、縮小、回転のためにこのようなワールド変換を行うとき、画像だけが拡大、縮小、回転するわけではないことに注意してください。つまり画像の表示位置に関しても座標が変換されるので、そのことも考慮して描画位置を指定する必要があります。 複合変換上記の例ではそれぞれの変換を独立して行うため、ワールド変換を指定する前にResetTransformメソッドにより、ワールド変換行列を単位行列にリセットしています。もしこのリセットを行わなければ、適用が指定されるすべての変換は次々と追加され、連続する複数の変換(複合変換)となります。 次にこのことを確認するため、リセットせずに平行移動後回転のワールド変換を設定してみます。 [VB.NET] 'PictureBox1のGraphicsオブジェクトを取得 Dim g As Graphics = PictureBox1.CreateGraphics() '画像を読み込む Dim img As Image = Image.FromFile("test.gif") '普通に画像を描画 g.DrawImage(img, New Rectangle(0, 0, img.Width, img.Height)) 'ワールド変換行列を右に平行移動する g.TranslateTransform(120, 0) '画像を描画 g.DrawImage(img, New Rectangle(0, 0, img.Width, img.Height)) 'ワールド変換行列を45度回転し、追加する g.RotateTransform(45.0F) '画像を描画 g.DrawImage(img, New Rectangle(0, 0, img.Width, img.Height)) 'リソースを開放する img.Dispose() g.Dispose() [C#] //PictureBox1のGraphicsオブジェクトを取得 Graphics g = PictureBox1.CreateGraphics(); //画像を読み込む Image img = Image.FromFile("test.gif"); //普通に画像を描画 g.DrawImage(img, new Rectangle(0, 0, img.Width, img.Height)); //ワールド変換行列を右に平行移動する g.TranslateTransform(120, 0); //画像を描画 g.DrawImage(img, new Rectangle(0, 0, img.Width, img.Height)); //ワールド変換行列を45度回転し、追加する g.RotateTransform(45F); //画像を描画 g.DrawImage(img, new Rectangle(0, 0, img.Width, img.Height)); //リソースを開放する img.Dispose(); g.Dispose();
この結果を見ると、回転後に平行移動していることが分かります。つまり、新しい変換は前に追加されるということが分かります。新しい変換を後ろに追加するために、MatrixOrder列挙体を指定することも出来ます。次の例では回転の操作を平行移動の後ろに追加してみましょう。 [VB.NET] 'Imports System.Drawing.Drawing2D 'がソースファイルの一番上に書かれているものとする 'PictureBox1のGraphicsオブジェクトを取得 Dim g As Graphics = PictureBox1.CreateGraphics() '画像を読み込む Dim img As Image = Image.FromFile("test.gif") '普通に画像を描画 g.DrawImage(img, New Rectangle(0, 0, img.Width, img.Height)) 'ワールド変換行列を右に平行移動する g.TranslateTransform(120, 0) '画像を描画 g.DrawImage(img, New Rectangle(0, 0, img.Width, img.Height)) 'ワールド変換行列を45度回転し、後ろに追加する g.RotateTransform(45.0F, MatrixOrder.Append) '画像を描画 g.DrawImage(img, New Rectangle(0, 0, img.Width, img.Height)) 'リソースを開放する img.Dispose() g.Dispose() [C#] //using System.Drawing.Drawing2D; //がソースファイルの一番上に書かれているものとする //PictureBox1のGraphicsオブジェクトを取得 Graphics g = PictureBox1.CreateGraphics(); //画像を読み込む Image img = Image.FromFile("test.gif"); //普通に画像を描画 g.DrawImage(img, new Rectangle(0, 0, img.Width, img.Height)); //ワールド変換行列を右に平行移動する g.TranslateTransform(120, 0); //画像を描画 g.DrawImage(img, new Rectangle(0, 0, img.Width, img.Height)); //ワールド変換行列を45度回転し、後ろに追加する g.RotateTransform(45F ,MatrixOrder.Append); //画像を描画 g.DrawImage(img, new Rectangle(0, 0, img.Width, img.Height)); //リソースを開放する img.Dispose(); g.Dispose();
平行移動後に回転されているのがお分かりいただけるでしょう。 これらの結果を見れば一目瞭然ですが、変換操作を後ろにするか前にするかという順番は場合によってはとても重要になります。このことに関してはヘルプ「変換順序が重要となる理由」にも詳しく書かれています。 |
|
Copyright 2002-2008 DOBON!. All rights reserved.
|