DrawEllipse: сглаживание не работает с PenAlignment.Inset

Как предложено @TaW на этот предыдущий вопрос, я установил PenAlignment.Inset для рисования круга внутри растрового изображения, но это вызвало другую проблему.


Я хочу нарисовать круг на указанном растровом изображении со сглаживанием.

SmoothingMode.AntiAlias

Проблема в том, что когда я использую PenAlignment.Inset, сглаживание работает неправильно!
Вместо этого, с PenAlignment.Center оно работает правильно...
Есть предложения по решению этой проблемы?

Bitmap layer = new Bitmap(80, 80);
using (Graphics g = Graphics.FromImage(layer))
{
    using (Pen p = new Pen(Color.Black, 4))
    {
        p.Alignment = PenAlignment.Inset;
        g.SmoothingMode = SmoothingMode.AntiAlias;
        g.DrawEllipse(p, new Rectangle(0, 0, layer.Width, layer.Height));
    }
}
pictureBox3.Size = new Size(100, 100);
pictureBox3.Image = layer;

правильное сглаживание сломанное сглаживание
(обратите внимание на ошибки на левом изображении)


person devpelux    schedule 29.05.2018    source источник


Ответы (1)


Сдувание ограничивающего прямоугольника на 1/2 ширины штриха пера должно решить эту проблему. Под «сдуванием» я подразумеваю вытягивание всех 4 сторон к центру прямоугольника на 1/2 ширины пера:

float halfPenWidth = p.Width*0.5f;
g.DrawEllipse(p, new RectangleF(halfPenWidth, halfPenWidth, layer.Width - p.Width, layer.Height - p.Width));

или подключив жестко заданную ширину пера 4:

g.DrawEllipse(p, new Rectangle(2, 2, layer.Width - 4, layer.Height - 4));

Обратите внимание, что полная ширина пера должна быть вычтена из ширины и высоты прямоугольника, чтобы вытянуть правую и нижнюю стороны на 1/2 ширины пера, сохраняя при этом центр прямоугольника в одной и той же точке.

При использовании этого кода с выравниванием пера по центру 1/2 ширины штриха будет отображаться за пределами прямоугольника в точках, где эллипс касается прямоугольника, но он все равно будет отображаться внутри растрового изображения.

person AndyP    schedule 29.05.2018
comment
Это заходит слишком далеко. Необходимо ввести только пиксели сглаживания; о ширине пера уже позаботились с помощью PenAlignment.Inset. Итак, rect.Inflate(-1, -1); следует сделать.. - person TaW; 29.05.2018
comment
Но я думаю, проблема в том, что @FirestormXYZ не может использовать PenAlignment.Inset, потому что в этом случае сглаживание работает неправильно. Таким образом, рисунок врезки необходимо смоделировать, установив для параметра PenAlignment значение «Центр» и уменьшив ограничительную рамку на 1/2 ширины пера. - person AndyP; 30.05.2018