10
votes

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

5
You probably want to Google, “Bresenham Circle” for the algorithm :-)BRPocock

5 Answers

11
votes

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

4
votes

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

4
votes

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);
      }
}
2
votes

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!

0
votes

Sorry for the delay This code works perfectly

private void drawcircle(int x,int y,int radius){
    for(int i=x;i<radius*2;i++)
        for(int j=x;j<radius*2;j++){
            int d= (int) Math.sqrt((i-radius)*(i-radius)+(j-radius)*(j-radius));
                if(d<radius)
                    pixels[i+j*WIDTH]=346346;
        }

}