0

I want to draw a circle with DrawEllipse on a specified Bitmap, with the same size of the Bitmap, but the result is that the circle appears clipped at the edges.
Why this problem?

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

drawellipse result

TaW
  • 53,122
  • 8
  • 69
  • 111
devpelux
  • 2,492
  • 3
  • 18
  • 38

1 Answers1

2

By default a Pen has a PenAlignment.Center.

This means that half of its widh will draw outside the bounding rectangle.

You can simply avoid the issue by changing it to PenAlignment.Inset:

using (Pen p = new Pen(Color.Black, 4) { Alignment = PenAlignment.Inset})
{
    g.DrawEllipse(p, new Rectangle(0, 0, layer.Width, layer.Height));
}

enter image description here

Update: If you want to turn on smoothing for the Graphics object you will need 1 or 2 extra pixels on both sides of the pen stroke for the anti-aliasing pixels. Using a smaller bounding rectanlge can't be avoided now. But..:

Rectangle rect = new Rectangle(Point.Empty, layer.Size);
rect.Inflate(-1, -1);  // or -2

..should do..

TaW
  • 53,122
  • 8
  • 69
  • 111
  • It works, but causes a problem with antialiasing mode: https://stackoverflow.com/q/50575461/3605220 – devpelux May 29 '18 at 02:28
  • That is true, antialiasing does take an extra pixel (on both sides of the pen stroke). No simple workaround that I know of, other than making the shape one pixel less high and wide. Which is less a drag than it sounds, considering the good old [difference](https://stackoverflow.com/questions/3147569/pixel-behaviour-of-fillrectangle-and-drawrectangle) between e.g. DrawRectangle and FillRectangle.. – TaW May 29 '18 at 02:59
  • 1
    I find that the `Inset` alignment of the `Pen` produces a result which is quite inferior than the `Center` alignment. I use this kind of reduction for the `Rectangle.Inflate()` method: `Rectangle.Inflate((int)(-(Pen.Width / 2) - 1), (int)(-(Pen.Width / 2)) - 1);` It works with both `SmoothingMode` set to `AntiAlias` and `HighQuality`. -1 is not need if there's no Antialiasing. – Jimi May 29 '18 at 15:48