Ink stroke drawing points using DrawEllipse (GDI +)

I am working on an application that draws handwritten strokes. Strokes are internally stored as point vectors and can be converted to std::vector<Gdiplus::Point>

. The points are so close to each other that a simple drawing of each point should result in a continuous impact.

I am using the Graphics.DrawEllipse

(GDI +) method to draw these points. Here's the code:

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

      

In the end, I just saved this one bitmap

as a PNG image and sometimes the following problem occurs:

problem

When I saw this "strong" "hole" in my punch, I decided to draw my glasses again, but this time using an ellipse with the width and height set to 1

, using redPen

the width set to 0.1f

. So right after the code above, I added the following code:

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

      

And the new stock I got looks like this: problem2

When I use Graphics.DrawRectangle

instead DrawEllipse

when drawing this new red stroke, it never happens that this stroke (drawn by drawing rectangles) will have different widths or holes in it:

rectangles

I can't think of any possible reason why drawing circles would lead to this strange behavior. Why is this stroke always permanent and never deformed in any way when I use it Graphics.DrawRectangle

? Can anyone explain what is going on here? Did I miss something?

By the way, I am using Windows XP (for example if this is a known bug). Any help would be appreciated.

+3


source to share


1 answer


I made the wrong assumption that if I use Graphics.DrawEllipse

to draw a circle with a radius of 2px with a feather about 2px wide, it will fill a circle with a diameter of about 4-5 px.
But I found that I actually cannot rely on the pen width by drawing a circle this way. This method is only for drawing the border of this shape, so it is much better to use it for drawing a filled ellipse Graphics.FillEllipse

.

Another important fact to keep in mind is that both of the functions mentioned take for the coordinates of the parameters that define the "upper-left corner of the rectangle that defines the boundaries of the ellipse" , so I have to subtract half the radius from both coordinates to make sure that the original coordinates indicate the middle of this circle.

Here's the new code:

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

      



which gives the following output:

correct stroke

So, in case someone comes across the same problem as me, the solution would be:

enter image description here

+2


source







All Articles