Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Graphics.DrawImage()在使用RotateTransform()时剪辑图像_C#_.net_Winforms_Graphics_Drawimage - Fatal编程技术网

C# Graphics.DrawImage()在使用RotateTransform()时剪辑图像

C# Graphics.DrawImage()在使用RotateTransform()时剪辑图像,c#,.net,winforms,graphics,drawimage,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.ToSiz

我有以下代码在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);
}
我的原始图像是:

但是旋转的结果并不像我预期的那样。90度缺少第一条红线,270度缺少第一个黑色列,180度缺少两者

如我所附的图片:

PS:您可以通过以下网址获得
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);

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

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

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

这将使位图的渲染速度有所降低,但用户可能感觉不到

虽然.NET文档在描述此设置方面没有太大帮助,但用于相同功能的本机Win32文档有稍微更详细的内容:
. 根据描述,可以推断,当像素的逻辑中心位于(0,0)时,旋转时可能会丢失一条边上的像素(和/或在另一条边上获得像素)。切换到
Half
可以解决这个问题。

你需要考虑一些事情

(1)
RotateTransforms
在当前原点应用旋转(如
矩阵中所述。旋转

(2) 默认值(当不使用附加参数的覆盖时)是
Prepend
。这意味着在您的情况下,生成的转换是旋转,然后平移

例如,如果将此代码放入绘制事件中:

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);
你会得到这个的

蓝色的矩形没有旋转。现在几乎固定原点(左上点)并开始顺时针旋转。您将看到它将与红色(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);
新的结果将是


一旦你理解了所有这些,希望你能对你的具体代码进行必要的修改。

我认为,使用
PixelOffsetModeHalf
它们是等价的。解释非常有趣,理解坐标的含义超出了
DrawImage
和旋转。我发现使用
Pen
创建抗锯齿像素与否,简单到
DrawLine
,取决于
Pen
是否具有奇数或偶数
Width
。PixelOffsetMode。在其他情况下,高质量还会导致一些不期望的结果,例如:
g.DrawLine(Pens.Red,0,0,100,0);g.DrawLine(Pens.Blue,0,1,100,1);
您将看到它在第一行只画了一条蓝线。请参见对不同问题的回答的解释@TaW提供了链接(在上面的评论中)。底线是,根据绘制时的不同设置,您将在不同的情况下获得不同的瑕疵。绘制线条时,您不必保持与绘制旋转位图时相同的
PixelOffsetMode
值;只需根据需要调整设置即可获得所需的结果。System.drawing使用浮点数学接口R通常,当浮点值被舍入为整数像素时,会出现“一对一”错误。Graphics.PixelOffsetMode的默认值是一个不吉利的选择,您必须更改它以消除这些舍入瑕疵。@HansPassant:在执行旋转变换后,起始坐标会更改。我刚刚添加了一个充足。看看你的屏幕截图,这显然不是你的问题,但你仍然缺少一个关键步骤:你需要确保你的图像具有与显示器相同的分辨率。它的分辨率为96dpi;我的显示器的分辨率为120dpi,无需纠正,图像看起来像屎,有无旋转。加载图像后插入此项: