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:
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:
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:
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.
source to share
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:
So, in case someone comes across the same problem as me, the solution would be:
source to share