我无法理解GDI +在曲面上画线的方式,可能有一些算法可以做到。
对于前。让我们采取10x10像素的表面。
Bitmap img = new Bitmap(10, 10);
现在让我们在这个表面上绘制一条线,宽度为5px,顶部偏移为5px。
using (var g = Graphics.FromImage(img))
{
g.Clear(Color.White);
var pen = new Pen(Color.Brown);
pen.Width = 5;
g.DrawLine(pen, 0F, 5F, 10F, 5F);
}
我们会得到:
绘图没有从像素#5开始,它从像素#4开始。 很明显,起点是单独计算的。但是如何?
我试图获得规律性,并得到了这个:
y = offset + width/2 - 1
其中y是实际起点y,偏移是选择起点y。
但在某些情况下,这不起作用。例如,让我们取宽度= 6,选择顶部偏移= 0,我们将得到y = 2,它将以这种方式绘制:
它必须显示6个像素,但它没有。
因此选择起点必须有更一般的算法,但我真的不知道它是什么。 任何帮助表示赞赏。
答案 0 :(得分:3)
线条图中没有offset
。您在DrawLine
方法中指定的坐标定义了线的中心。顶部像素为y - width / 2
,底部为y - width / 2 + width - 1
。第二个公式考虑了width / 2
向下舍入的事实。此外,顶行为y = 0
,底线为y = 9
。那么,对你来说第一行:
top = 5 - (5 / 2) = 3
bottom = 5 - (5 / 2) + 5 - 1 = 7
和第二行:
top = 2 - (6 / 2) = -1
bottom = 2 - (6 / 2) + 6 - 1 = 4
顶边被剪裁到位图的边缘,因此线宽减小了。
答案 1 :(得分:1)
在第一个示例中,它看起来像一条宽度为5像素的行,以第5行为中心(计数从0开始,而不是1)。 这似乎是一个合理的结果。
在第二个示例中,它看起来像一条宽度为6的线,位于第1行和第2行之间,顶行被切掉,因为它超出了图像的边界。
答案 2 :(得分:0)
GDI +中的坐标不指定像素本身,而是指定其中心的(无限小)点。因此(0f,5f)
表示第一列和第六行中像素的中心(因为计数从零开始)。因此,从现在开始,我将区分坐标和像素行。
绘制直线时,GDI +概念性地沿着这些坐标定义的直线移动指定宽度的笔。请注意,您可以通过指定Pen.StartCap
和Pen.EndCap
在行的开头和结尾定义此笔的确切形状。
由于您指定了宽度5f
并且您正在绘制一条水平线,因此该行将2.5
像素扩展到顶部和底部,从而覆盖从#3到(包括)的完整像素行#7。请注意,根据上面的定义,像素行#3的上边缘具有y坐标2.5
,行#7的下边缘具有7.5
,即{分别为{1}}和5f-2.5f
我没有得到与你的第二个例子相同的结果(我试过Try GDI+ application)。相反,我得到一条覆盖前三个像素行的线。从理论上讲,它甚至应该覆盖前3.5个prows(因为坐标指定第一行的 center ,上部只是被剪裁)。但是如果关闭抗锯齿,底部的“半行”会被截断。
这可以通过将5f+2.5f
设置为g.SmoothingMode
来显示,在这种情况下,第四行是透明绘制的。使用抗锯齿时,您还会注意到,第一个和最后一个列未完全绘制,因为起始坐标同样位于列的中心。