2016-03-21 10 views
3

私はGraphics.drawImageを()のクリップの画像RotateTransformを使用して()

private void Form1_Paint(object sender, PaintEventArgs e) 
{ 
    Bitmap border = new Bitmap("border2.bmp"); 
    int borderThick = border.Height; 

    Graphics g = e.Graphics; 
    Size region = g.VisibleClipBounds.Size.ToSize(); 

    Rectangle desRectW = new Rectangle(0, 0, region.Width - borderThick, borderThick); 

    // 1. LEFT - RIGHT border 
    g.TranslateTransform(30, 30); 
    g.DrawImage(border, desRectW, desRectW, GraphicsUnit.Pixel); 

    // 2. UP - BUTTOM border 
    g.ResetTransform(); 
    g.TranslateTransform(50, 50); 
    g.RotateTransform(90); 
    g.DrawImage(border, desRectW, desRectW, GraphicsUnit.Pixel); 

    // 3. RIGHT-LEFT border 
    g.ResetTransform(); 
    g.TranslateTransform(100, 100); 
    g.RotateTransform(180); 
    g.DrawImage(border, desRectW, desRectW, GraphicsUnit.Pixel); 

    // 4. BOTTOM - UP border 
    g.ResetTransform(); 
    g.TranslateTransform(150, 150); 
    g.RotateTransform(270); 
    g.DrawImage(border, desRectW, desRectW, GraphicsUnit.Pixel); 
} 

border2.bmp 4で方向を描画するコードを以下している私の元の画像は、次のとおりです。

enter image description here

しかし結果私が期待していたものとまったく同じではありません。 90度は最初の赤線がなくなり、270度は最初の黒線がなくなり、180度は両方とも欠けている。

は画像のように、私は添付:

enter image description here

PSを:http://i.imgur.com/pzonx3i.png

編集:あなたはborder2.bmpで取得することができ を私は@Peter Dunihoコメントとしてg.PixelOffsetMode = PixelOffsetMode.HighQuality;を試してみましたが、私はそれがまたいました正しく描く。 例:4行は、期待どおりの位置で開始していません。

g.TranslateTransform(50, 50); 

// LEFT - RIGHT border 
g.DrawLine(Pens.Red, 0, 0, 100, 0); 

// UP - BOTTOM border 
g.RotateTransform(90); 
g.DrawLine(new Pen(Color.FromArgb(128, Color.Blue)), 0, 0, 100, 0); 

// RIGHT-LEFT border 
g.RotateTransform(90); 
g.DrawLine(new Pen(Color.FromArgb(128, Color.Green)), 0, 0, 100, 0); 

// BOTTOM - UP border 
g.RotateTransform(90); 
g.DrawLine(new Pen(Color.FromArgb(128, Color.Gray)), 0, 0, 100, 0); 
+1

System.Drawingは、浮動小数点数を内部的に使用するため、浮動小数点値が整数ピクセルに丸められたときにオフバイアエラーが発生します。 Graphics.PixelOffsetModeのデフォルト値は不運な選択でしたが、これらの丸めのアーティファクトを取り除くには、これを変更する必要があります。 –

+0

@HansPassant:RotateTransformの実行後に開始座標が変更されます。私は例を追加しました。 – KevinBui

+1

あなたのスクリーンショットを見ると、これはあなたの問題ではありませんが、依然として重要な一歩がありません。あなたのイメージがあなたのモニターと同じ__解像度__を持つことを確認してください。それは96dpiを持っています。私のモニターは120dpiを持っていて、イメージは回転の有無にかかわらずshiteのように見えます。イメージをロードした後にこれを挿入します: '(graphics gr = this.CreateGraphics())img.SetResolution(gr.DpiX、gr。 DpiY); '! – TaW

答えて

3

これがなぜ起こるか私は本当にすべてのグラフィックスAPIは、必ずしも常時不正確な行動につながり、あなたがここにそのような状況に実行されているように見えるかもしれ最適化を含めるために起こっていることを除いて、説明することはできません。あなたの特定の例では

あなたが画像を描画する前に、問題は、コードに次のステートメントを追加することによって補正することができます:Halfに設定

g.PixelOffsetMode = PixelOffsetMode.HighQuality; 

も動作します。これはHighQualityに相当します(または、技術的には、HighQualityは…と同等ですが、私はHighQualityというコードで説明しています:))。

これにより、ビットマップのレンダリングが多少遅くなりますが、おそらくユーザーが知覚できる方法ではありません。 PixelOffsetMode enumeration:.NETドキュメントは、この設定を記述するという点で非常に有用ではありませんが

、同じ機能をネイティブのWin32ドキュメントは少し詳細を持っています。この説明から、(0,0)のピクセルの論理的な中心で、回転するとき(および/または別のエッジのピクセルを獲得するとき)、あるエッジでピクセルを失う可能性があることが推論できます。 Halfに切り替えるとこれが修正されます。

+0

と思う、とにかく、彼らは 'PixelOffsetModeHalf'を使用して同等である、少し明確です。説明は非常に面白く、座標の意味が「DrawImage」と回転を超えていることを理解する。アンチエイリアス化されたピクセルを生成するか否かを示す '' Pen''を持つ 'DrawLine'のようなものには、[同じ問題が適用されます](http://stackoverflow.com/questions/36094055/adding-antialiasing/36095479#36095479)が見つかりました、例えば – TaW

+0

PixelOffsetMode.HighQualityは、他の状況で予期しない結果を引き起こす可能性があります。 例: 'g.DrawLine(Pens.Red、0、0、100、0) ; g.DrawLine(Pens.Blue、0、1、100、1); ' 最初の行に青い線のみが表示されます。 – KevinBui

+2

別の質問への回答の説明を参照してください@TaW(上記のコメント)へのリンクを提供しました。結論は、描画するときのさまざまな設定に応じて、さまざまな状況で異なるアーティファクトを取得することです。回転したビットマップを描画するときと同じように線を描画するときに、同じ 'PixelOffsetMode'値を保持する必要はありません。必要な結果を得るために必要に応じて設定を調整するだけです。 –

0

いくつかのことを考慮する必要があります。

Matrix.Rotatedocumentation

で説明したように(1)RotateTransforms(2)追加の引数を指定して上書きを使用して指定されていないデフォルトMatrixOrder()はPrependある現在原点(AT回転を適用する。どのあなたの場合、結果の変換が回転してから変換されることを意味します。例えば

、あなたがペイントイベント内でこのコードを置く場合:

var g = e.Graphics; 
var loc = new Point(128, 128); 
var rect = new Rectangle(0, 0, 64, 16); 

g.ResetTransform(); 
g.TranslateTransform(loc.X, loc.Y); 
g.FillRectangle(Brushes.Blue, rect); 

g.ResetTransform(); 
g.TranslateTransform(loc.X, loc.Y); 
g.RotateTransform(90); 
g.FillRectangle(Brushes.Red, rect); 

g.ResetTransform(); 
g.TranslateTransform(loc.X, loc.Y); 
g.RotateTransform(180); 
g.FillRectangle(Brushes.Green, rect); 

g.ResetTransform(); 
g.TranslateTransform(loc.X, loc.Y); 
g.RotateTransform(270); 
g.FillRectangle(Brushes.Magenta, rect); 

あなたは青い四角形が回転しないこの

enter image description here

取得します。原点(左上の点)を仮想的にピン止めし、時計回りに回転を開始します。 Red(90)、Green(180)、およびMagenta(270)の四角形と正確に一致することがわかります。

矩形を形成する場合は、回転した長方形にオフセット(平行移動)を追加する必要があります。重なり領域をどのように処理するかによって異なりますが、赤い矩形を右に青く連結したい場合は、青の矩形Width +元の矩形の高さをX方向に追加する必要があります。他の回転した矩形に対しても、同様のオフセットをX、Y、またはその両方に適用できます。サンプルを完了するために、

、我々はこの

var g = e.Graphics; 
var loc = new Point(128, 128); 
var rect = new Rectangle(0, 0, 64, 16); 

g.ResetTransform(); 
g.TranslateTransform(loc.X, loc.Y); 
g.FillRectangle(Brushes.Blue, rect); 

g.ResetTransform(); 
g.TranslateTransform(loc.X + rect.Width + rect.Height, loc.Y); 
g.RotateTransform(90); 
g.FillRectangle(Brushes.Red, rect); 

g.ResetTransform(); 
g.TranslateTransform(loc.X + rect.Width + rect.Height, loc.Y + rect.Width + rect.Height); 
g.RotateTransform(180); 
g.FillRectangle(Brushes.Green, rect); 

g.ResetTransform(); 
g.TranslateTransform(loc.X, loc.Y + rect.Width + rect.Height); 
g.RotateTransform(270); 
g.FillRectangle(Brushes.Magenta, rect); 

のようにコードを変更する場合は、すべてのことを理解すれば、新たな結果はあなたが必要な修正を適用することを願って、

enter image description here

になりますあなたの具体的なコードに

関連する問題