FillRectangle和DrawRectangle的像素行为

时间:2010-06-30 08:28:11

标签: .net gdi+

几乎每次我使用Graphics.DrawRectangleGraphics.FillRectangleint版本)时,我似乎都会错过我想要绘制的矩形的右下边框上的像素。

填充哪些像素的确切定义是什么
Graphics.FillRectangle(brush,x,y,width,height)

Graphics.DrawRectangle(pen,x,y,width,height) // pen is one pixel width, i.e. width=0f

是否有合理的解释? (所以我终于可以记住行为:) ...)

修改

使用Oleg Zhuk奇妙的Try GDI+应用程序,我能够找到FillRectangleDrawRectangle之间的奇怪差异:

FillRectangle(brush,0,0,1,1)在(0,0)处绘制一个点,这在某种程度上是可以理解的(它毕竟是宽度和高度的矩形)。

另一方面,

DrawRectangle(pen,0,0,1,1)绘制一个2×2像素的小矩形。

对于其他宽度/高度组合显示相同的行为,DrawRectangle总是向左和向下延伸一个像素(这有点令人讨厌,例如当使用ClientRectangle属性绘制时框架周围的框架)

我的第一个问题解决了( 他们的行为......)仍然存在第二个问题:为什么他们的行为方式如何?

3 个答案:

答案 0 :(得分:7)

这些方法可以正常工作,您只需要考虑抗锯齿和舍入的效果。

首先,打开消除锯齿以查看所有内容(不仅是舍入结果):

graphics.SmoothingMode = SmoothingMode.AntiAlias;

现在FillRectangle(10,10,10,10)会产生模糊的结果而DrawRectangle(10,10,10,10)会很清晰。

模糊结果表示您有像素坐标离网。如果您需要致电:

graphics.FillRectangle(9.5f, 9.5f, 10, 10);

将矩形的左上角对齐网格。

DrawRectangle很清晰,因为它使用宽度为1.0的Pen。因此,线条从像素中心开始,在两个方向上都是0.5像素,因此恰好填充了1个像素。

请注意,宽度和高度以这种方式计算:

width = (right - left) = 19.5 - 9.5 = 10
height = (bottom - top) = ...

请注意,19.5是矩形的右/底坐标,也在网格上对齐,结果是整数。

您可以使用不同的公式:

width2 = (right - left + 1)

但这仅适用于圆形坐标,因为最小单位为1像素。使用抗锯齿的GDI +时,请注意这个点的大小为零,并且位于像素的中心(它不是整个像素)。

答案 1 :(得分:1)

问题中两个Graphics方法中的矩形左下角为(x, y),右下角为(x + width - 1, y + height - 1)。这是指定宽度和高度而不是右下角的结果。

当你从两点计算宽度和高度时,你记得通过在差值上加1来包括原点像素。

例如,假设您要从点(5,5)到点(10,20)填充矩形。矩形的宽度为6,而不是5.矩形的高度为16,而不是15。

答案 2 :(得分:-2)

行为上的差异是由于这两种算法做了完全不同的事情有点反直觉的事实。

DrawRectangle以框的形状绘制四条线。 FillRectangle生成一个填充像素的W * H块。从中可以很容易地看出行为差异的原因。即相似性假设的错误。绘制四条线与生成像盒状像素块完全不同。