Я работаю над приложением, которое рисует рукописные штрихи. Штрихи внутренне хранятся как векторы точек, и они могут быть преобразованы в 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 и иногда возникает следующая проблема:
Когда я увидел это «дыра» в моем инсульте, Я решил снова нарисовать свои точки, но на этот раз, используя эллипс с шириной и высотой, установленными в 1
используя 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 (например, если это известная ошибка). Любая помощь будет оценена.
Я сделал неверное предположение, что если я использую 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);
который дает следующий результат:
Поэтому, если кто-то столкнется с той же проблемой, что и я, решение будет таким:
Других решений пока нет …