使用RotateTransform()时,Graphics.DrawImage()剪辑图像

时间:2016-03-21 04:33:35

标签: c# .net winforms graphics drawimage

我有以下代码在4方向上绘制我的border2.bmp

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

我的原始图片是:

enter image description here

但轮换的结果并不完全符合我的预期。第一条红线缺少90度,第一条黑柱缺少270度,两条线都缺失180度。

像我附上的图片一样:

enter image description here

PS:您可以在http://i.imgur.com/pzonx3i.png

获得border2.bmp

编辑: 我尝试g.PixelOffsetMode = PixelOffsetMode.HighQuality;作为@Peter Duniho评论,但我发现它也没有正确绘制。 示例: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);

2 个答案:

答案 0 :(得分:3)

我无法解释为什么会发生这种情况,除了任何图形API都必然包含可能导致行为不精确的优化,而且似乎你遇到了这种情况。

在您的特定示例中,可以通过在绘制图像之前将以下语句添加到代码来更正此问题:

do_somthing(a,b,bar.empty()? the_default_argument : bar);

将其设置为g.PixelOffsetMode = PixelOffsetMode.HighQuality; 也可以。它相当于Half(或者从技术上讲,HighQuality相当于......但我在代码中发现HighQuality更具描述性。)。

这会稍微降低位图的渲染速度,但可能不会让用户感觉到这种情况。

虽然.NET文档在描述此设置方面没有什么帮助,但同一功能的原生Win32文档有略微更多详细信息: PixelOffsetMode enumeration。根据该描述,可以推断出,在(0,0)处像素的逻辑中心,当旋转(和/或在另一边缘上获得像素)时,可能在一个边缘上丢失像素。切换到HighQuality会解决此问题。

答案 1 :(得分:0)

你需要考虑一些事情。

(1)RotateTransforms在当前来源处应用轮播(如Matrix.Rotate documentation

中所述

(2)默认MatrixOrder(未使用带有附加参数的覆盖指定时)为Prepend。这意味着在您的情况下,生成的转换是旋转,然后转换。

例如,如果将此代码放在paint事件中:

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

蓝色矩形未旋转。现在实际上固定原点(左上角)并开始顺时针旋转。您将看到它与红色(90),绿色(180)和洋红色(270)矩形完全匹配。

这意味着如果你想形成一个矩形,你需要对旋转的矩形应用额外的偏移(平移)。这取决于你想要如何处理重叠区域,但是对于样本,如果我们想要将红色矩形连接到蓝色矩形,我们需要在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

一旦您理解了所有这些,希望您可以对您的具体代码进行必要的更正。