【问题标题】:Drawing points of handwritten stroke using DrawEllipse (GDI+)使用 DrawEllipse (GDI+) 绘制手写笔画点
【发布时间】:2013-01-22 22:27:31
【问题描述】:

我正在开发一个绘制手写笔画的应用程序。笔划在内部存储为点向量,它们可以转换为std::vector<Gdiplus::Point>。点彼此如此接近,每个点的简单绘制应该会产生连续笔划的图像。

我正在使用Graphics.DrawEllipse (GDI+) 方法来绘制这些点。代码如下:

// prepare bitmap:
Bitmap *bitmap = new Gdiplus::Bitmap(w, h, PixelFormat32bppRGB);
Graphics graphics(bitmap);

// draw the white background:
SolidBrush myBrush(Color::White);
graphics.FillRectangle(&myBrush, 0, 0, w, h);

Pen blackPen(Color::Black);
blackPen.SetWidth(1.4f);

// draw stroke:
std::vector<Gdiplus::Point> stroke = getStroke();
for (UINT i = 0; i < stroke.size(); ++i)
{
    // draw point:
    graphics.DrawEllipse(&blackPen, stroke[i].X, stroke[i].Y, 2, 2);
}

最后我只是将这个bitmap保存为PNG图像,有时会出现以下问题:

当我在我的笔划中看到这个“洞”时,我决定再次绘制我的点,但这一次,使用宽度和高度设置为@的椭圆987654331@ 使用 redPen 并将宽度设置为 0.1f。所以在上面的代码之后我添加了以下代码:

Pen redPen(Color::Red);
redPen.SetWidth(0.1f);

for (UINT i = 0; i < stroke.size(); ++i)
{
    // draw point:
    graphics.DrawEllipse(&redPen, stroke[i].X, stroke[i].Y, 1, 1);
}

我得到的新斯托克看起来像这样:

当我在绘制这个新的红色笔划时使用Graphics.DrawRectangle 而不是DrawEllipse 时,这个笔划(通过绘制矩形绘制)不会有不同的宽度或孔:

我想不出任何可能的原因,为什么画圈会导致这种奇怪的行为。为什么当我使用Graphics.DrawRectangle 时,笔触总是连续的并且从未以任何方式变形? 谁能解释一下,这是怎么回事?我错过了什么吗?

顺便说一下,我使用的是 Windows XP(例如,如果它是一个已知的错误)。任何帮助将不胜感激。

【问题讨论】:

    标签: c++ drawing gdi+ point drawellipse


    【解决方案1】:

    我做出了错误的假设,如果我使用Graphics.DrawEllipse 绘制一个半径等于 2px 且笔宽约 2px 的圆,它将导致绘制一个直径约 4-5 px 的实心圆。
    但我发现,这样画圆时,我实际上不能依赖笔的宽度。此方法仅用于绘制这种形状的边框,因此绘制填充椭圆最好使用Graphics.FillEllipse

    另一个需要考虑的非常重要的事实是,上述两个函数都将坐标作为参数,指定“指定椭圆边界的矩形的左上角”,所以我应该从两个坐标中减去一半的半径,以确保原始坐标指定这个圆的中间。

    这是新代码:

    // draw the white background:
    SolidBrush whiteBrush(Color::White);
    graphics.FillRectangle(&whiteBrush, 0, 0, w, h);
    
    // draw stroke:
    Pen blackBrush(Color::Black);
    std::vector<Gdiplus::Point> stroke = getStroke();
    for (UINT i = 0; i < stroke.size(); ++i)
        graphics.FillEllipse(&blackBrush, stroke[i].X - 2, stroke[i].Y - 2, 4, 4);
    
    // draw original points:
    Pen redBrush(Color::Red);
    std::vector<Gdiplus::Point> origStroke = getOriginalStroke();
    for (UINT i = 0; i < origStroke.size(); ++i)
        graphics.FillRectangle(&redBrush, origStroke[i].X, origStroke[i].Y, 1, 1);
    

    产生以下结果:

    所以万一有人遇到和我一样的问题,解决办法是:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-10
      • 2010-11-04
      • 2023-02-26
      • 2015-11-10
      • 1970-01-01
      • 2011-01-01
      • 1970-01-01
      • 2013-04-05
      相关资源
      最近更新 更多