16

What's a good algorithm for drawing anti-aliased circles? (Filled and not filled.)

fmsf
  • 36,317
  • 49
  • 147
  • 195

4 Answers4

10

Bresenham (of the line algorithm fame) also had a circle algorithm.

Xiaolin Wu adapted the line algorithm for anti-aliasing, and likewise did the same to the circle algorithm.

http://en.wikipedia.org/wiki/Xiaolin_Wu%27s_line_algorithm

You can find the circle algorithm with this search:

http://www.google.com/search?q=Xiaolin%20Wu%20circle

-Adam

Adam Davis
  • 91,931
  • 60
  • 264
  • 330
  • 1
    Actually, what is popularly known as "Bresenham's circle algorithm" wasn't Bresenham's own work. http://en.wikipedia.org/wiki/Midpoint_circle_algorithm But still.... – Stewart May 28 '10 at 12:10
5

If you want an easy one, make a soft blur from pixel matrix A to pixel matrix B.

This is one i've used (here in pseudo-code)

anti_alised_matrix[x][y] = point[x][y] / 2 + point[x+1][y]/8 + point[x-1][y]/8 + point[x][y-1]/8 + point[x][y+1]/8;

Ofcourse this is applied to grayscale, but you can do easily the same in RGB.

This is really a very simple one, you can also add the diagonals i.e. [x+1][y+1] and split it by 16 or 32.

fmsf
  • 36,317
  • 49
  • 147
  • 195
0

For everyone in need. I've just wrote a circle drawer function for my app.

Unfortunately it draws only odd diameter circles, but it's very fast for drawing on CPU.

Also it can be easily ported on any other language since no special syntax/constructions are used.

The main advantage is that it can work with the blending, avoiding layering of pixels (which is leading to dark spots on the circle).

/*
* void drawPixel(int32_t x, int32_t y, uint32_t color)
*
* The algorithm's been written assuming this function to work with alpha-blending
* and packed RGBA colors, but you can change the color system easily.
* 
* AA - anti-aliasing 
*/

static inline void draw8Symmetry(int32_t cX, int32_t cY, int32_t x, int32_t y, int32_t color) {
    drawPixel(cX + x, cY + y, color);
    drawPixel(cX + x, cY - y, color);
    if (x != 0) {  // No repeating on top/bottom
        drawPixel(cX - x, cY + y, color);
        drawPixel(cX - x, cY - y, color);
    }
    if (x != y) { // No repeating on corners (45 deg)
        drawPixel(cX + y, cY + x, color);
        drawPixel(cX - y, cY + x, color);
        if (x != 0) { // No repeating on left/right sides
            drawPixel(cX + y, cY - x, color);
            drawPixel(cX - y, cY - x, color);
        }
    }
}

void drawCircle(int32_t cX, int32_t cY, int32_t r, uint32_t color) {
    int32_t i = 0;
    int32_t j = r + 1;
    int32_t rr = r * r;

    double lastFadeAmount = 0;
    double fadeAmount = 0;
    int32_t fadeAmountI;

    const int32_t maxOpaque = color >> 24;
    const int32_t noAlphaColor = color & 0x00FFFFFF;

    while (i < j) {
        double height = sqrt(rr - i * i);
        fadeAmount = (double)maxOpaque * (1.0 - (ceil(height) - height));

        // If fade amount is dropping, then, obviously, it's a new step
        if (fadeAmount > lastFadeAmount)
            j--;
        lastFadeAmount = fadeAmount;
        
        // Draw the semi-transparent circle around the filling
        draw8Symmetry(cX, cY, i, j, noAlphaColor | ((int32_t)fadeAmount << 24));

        // Draw central filling
        if (i != 0)
            for (int32_t x = -j + 1; x < j; x++) {
                drawPixel(cX + x, cY + i, color);
                drawPixel(cX + x, cY - i, color);
            }
        else
            for (int32_t x = -j + 1; x < j; x++)
                drawPixel(cX + x, cY + i, color);

        i++;
    }

    // Draw top and bottom parts
    while (i < r) {
        int32_t lineLength = ceil(sqrt(rr - i * i));

        for (int32_t x = -lineLength + 1; x < lineLength; x++) {
            drawPixel(cX + x, cY + i, color);
            drawPixel(cX + x, cY - i, color);
        }

        i++;
    }
}
LiaVa
  • 198
  • 1
  • 10
-11

Create a Graphics object g. Do

g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

Draw your anti aliased circle with g.FillEllipse or g.DrawEllipse

Spikolynn
  • 4,067
  • 2
  • 37
  • 44