Draw circle (using pixels applied in an image with for loop)

37,474

Solution 1

Here is the code for drawing circle with pixels: It uses the formula xend = x + r cos(angle) and yend = y + r sin(angle).

#include <stdio.h>
#include <graphics.h>
#include <stdlib.h>
#include <conio.h>
#include <bios.h>
#include <math.h>

void DrawCircle(int x, int y, int r, int color)
{
      static const double PI = 3.1415926535;
      double i, angle, x1, y1;

      for(i = 0; i < 360; i += 0.1)
      {
            angle = i;
            x1 = r * cos(angle * PI / 180);
            y1 = r * sin(angle * PI / 180);
            putpixel(x + x1, y + y1, color);
      }
}

Reference: http://www.softwareandfinance.com/Turbo_C/DrawCircle.html

Solution 2

You can calculate the minimum angle between two pixels and improve the Kathir solution

...
void DrawCircle(int x, int y, int r, int color)
{
      static const double PI = 3.1415926535;
      double x1, y1;

      // calculates the minimun angle between two pixels in a diagonal.
      // you can multiply minAngle by a security factor like 0.9 just to be sure you wont have empty pixels in the circle
      double minAngle = acos(1 - 1/r);

      for(double angle = 0; angle <= 360; angle += minAngle)
      {
            x1 = r * cos(angle);
            y1 = r * sin(angle);
            putpixel(x + x1, y + y1, color);
      }
}

Solution 3

Since you already have a BufferedImage, why not create a graphics object for it and use that to draw the circle? That way you don't have to reinvent the wheel:

    BufferedImage img = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
    Graphics2D g = img.createGraphics();
    g.setColor(Color.WHITE);
    g.fillOval(x, y, width, height);

Update

Here is a SSCCE:

public class DrawCircleExample extends Canvas {
    private static final int WIDTH = 32;
    private static final int HEIGHT = 32;

    public static void main(String[] args) {
        JFrame f = new JFrame("Draw circle example");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(new DrawCircleExample());
        f.pack();
        f.setVisible(true);
    }

    private final BufferedImage img;

    public DrawCircleExample() {
        img = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = img.createGraphics();
        g.setColor(Color.WHITE);
        g.fillOval(8, 8, 14, 14);
    }

    @Override
    public void paint(Graphics g) {
        g.drawImage(img, 0, 0, null);
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(img.getWidth(),img.getHeight());
    }
}

It should produce an image like this:

Example output from circle example

Solution 4

One way to do this would be to test, for each point in the rectangle, whether or not the distance from that pixel to the center of the square is less than the intended radius of the circle. You could then draw the pixels that pass the test and skip the pixels that don't. The ratio of the area of the circle to the area of the total square is π/4, which is about .77, so this actually isn't all that inefficient.

If you want to draw an arbitrary oval that fits in the rectangle, you can use this same idea, but would modify the computation that would determine the distance to the center such that you give proportionally less weight to the long axis of the ellipse.

Hope this helps!

Share:
37,474
Ionel Lupu
Author by

Ionel Lupu

Updated on October 31, 2020

Comments

  • Ionel Lupu
    Ionel Lupu over 3 years

    I want to draw a circle (with 1 or 2 for loops) using pixels position (starts from top left and ends at bottom right)

    I successfully drew a rectangle with this method:

    private void drawrect(int width,int height,int x,int y) {
        int top=y;
        int left=x;
    
        if(top<0){
            height+=top;
            top=0;
            }
        if(left<0){
            width+=left;
            left=0;
        }
    
        for (int j = 0; j <width; j++) {
            for (int i = 0; i <height; i++) {
                        pixels[((i+top)*w)+j+left] = 0xffffff;//white color
            }
    
        }
    
    }
    

    The pixels array contains the pixel index followed by it's color.

    pixels[index]=color;
    

    Before that I use this code for "image" and "pixels" array (if this helps you)

    img = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
    pixels = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
    

    But how can I draw only the white pixels like in this image and ignore the other pixels?

    Pixel Image

  • Ionel Lupu
    Ionel Lupu over 12 years
    I don't know why but i can't see the oval.My frame is blank. BTW. For rendering i'm using an imagine big like my frame
  • Kevin K
    Kevin K over 12 years
    I added the test code I was using as an example. Does that help?
  • Ionel Lupu
    Ionel Lupu over 12 years
    i'm using f.add(class_object);So because of this nothing works.add this to your code DrawCircleExample circle=new DrawCircleExample();f.add(circle); but write near public class DrawCircleExample this extends Canvas
  • Kevin K
    Kevin K over 12 years
    You need to overwrite the the paint method of the Canvas to draw the image on the canvas. I updated the example.
  • Nicolas Raoul
    Nicolas Raoul almost 11 years
    Double loop is slow, you could use a single loop to do the same job. To further increase performance, you could then do four times less square and squareroot operations by exploiting the two symmetries.
  • rbaleksandar
    rbaleksandar over 8 years
    bios.h, graphics.h... Seriously tons of unnecessary dependencies. And on top of that you have math.h, which has a PI constant in it yet you go define your own...
  • ostrichofevil
    ostrichofevil over 8 years
    If your circle is too big, then this won't work; you'll just get 360 points arranged in a circle with nothing in between.
  • Shai Segev
    Shai Segev about 7 years
    If you need to contour only: if (d >= radius -1 && d < radius + 1) img.SetPixel(i , j,Color.White);
  • Apostolos
    Apostolos about 6 years
    Great! It's the 6th (or so) and definitely the best circle algorithm I have tried this evening. Not only from cohesiveness and density aspect, but also from a drawing view: it follows exactly a circle trajectory (never seen that and love it.) And one more advantage: one can "play" with the 'step' to draw the circle faster. In fact, there's no need for 3,600 points. 720 points, using a 0.5 step, are already just fine. Upvoted.