How can i clear a circle with Graphics2D.

I have a BufferedImage and its Graphics2D. I want to clear a circle out of it, basically make the circle transparent and also have the cleared circles border be properly antialiased. I have used a Graphics2D alot but i dont know how this can be done.
LVL 17
Thomas4019Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

 
Thomas4019Author Commented:
Note, i would like to do something like fillOval() or fillShape(new Ellipse2D() but if i set the color to transparent then when it draws the oval it has no effect. Would alpha premultiplying help me and how could this be done.
0
 
objectsCommented:
you cannot clear it, you need to paint over it
0
 
InteractiveMindCommented:
I've coded you a function which will produce a buffered image of a specific colour, with a circle of a specified radius missing from the centre (it's anti-aliased too). Just call it, and then render the returned BufferedImage on top of your own when necessary. I've attached an example image of the result.

Note: if you adjust the 'dg' variable (>0) in the method, it will change the magnitude of the blurring/softening around the edge. I think dg=2 is good enough though.

		/* r - red component
		 * g - green
		 * b - blue
		 * w - width of image
		 * h - height of image
		 * rad - radius of image
		 */
		public BufferedImage circleThing(int r, int g, int b, int w, int h, int rad)
		{
			if(2*rad>Math.min(w,h)) return null;
			
			BufferedImage bimg=new BufferedImage(w,h,BufferedImage.TYPE_INT_ARGB);
			Graphics2D G=(Graphics2D)bimg.getGraphics();
			
			G.setColor(new Color(r,g,b,255));
			
			G.fillRect(0,0,w,(h>>1)-rad);
			G.fillRect(0,(h>>1)-rad,(w>>1)-rad,2*rad);
			G.fillRect((w>>1)+rad,(h>>1)-rad,(w>>1)-rad,2*rad);
			G.fillRect(0,(h>>1)+rad,w,(h>>1)-rad);
			
			double dg=2;
			for(int i=-rad; i<=rad; i++)
				for(int j=-rad; j<=rad; j++)
				{
					double d=Math.sqrt(i*i+j*j);
					if(d>rad)
					{
						G.setColor(new Color(r,g,b,255));
						G.fillRect((w>>1)+i,(h>>1)+j,1,1);
					}else if(Math.abs(d-rad)<dg)
					{
						double gap=Math.abs(d-rad);
						int op=(int)((1.0-gap/dg)*255.0);
						G.setColor(new Color(r,g,b,op));
						G.fillRect((w>>1)+i,(h>>1)+j,1,1);
					}
				}
			
			G.dispose();
			return bimg;
		}

Open in new window

example.jpg
0
Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

 
InteractiveMindCommented:
Actually, dg=1 is more like it.
Here's an example of use (just me showing off a bit).
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
 
public class Example extends JFrame
{
	public Example()
	{
		super("Example");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		add(new Display(500,400));
		pack();
		setLocationRelativeTo(null);
		setVisible(true);
	}
	
	public static void main(String[]a)
	{
		new Example();
	}
	
	class Display extends JComponent implements Runnable
	{
		private int w,h;
		private Image img=null;
		private int t=0;
		private double p=0;
		
		public Display(int w, int h)
		{
			this.w=w;
			this.h=h;
			setPreferredSize(new Dimension(w,h));
			img=new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);
			Graphics g=img.getGraphics();
			g.setColor(new Color(0xEFEFEF));
			g.fillRect(0,0,w,h);
			g.setColor(new Color(0x888888));
			int m=10;
			for(int j=0; j<h/m; j++)
			{
				for(int i=0; i<w/m; i++)
				{
					if((i+j)%2==0)
					{
						g.fillRect(i*m,j*m,m,m);
					}
				}
			}
			g.dispose();
			
			new Thread(this).start();
		}
		
		public void run()
		{
			for(;;)
			{
				t+=2;
				t%=w;
				p+=.05;
				p%=2*Math.PI;
				repaint();
				try{Thread.sleep(20);}catch(Exception e){}
			}
		}
		
		public void paint(Graphics gg)
		{
			Graphics2D g=(Graphics2D)gg;
			
			g.drawImage(img,t,0,w,h,null);
			g.drawImage(img,t-w,0,w,h,null);
			
			g.drawImage(circleThing(255,255,255,w,h,(int)(100+50*Math.cos(p))),0,0,null);
		}
		
		public BufferedImage circleThing(int r, int g, int b, int w, int h, int rad)
		{
			if(2*rad>Math.min(w,h)) return null;
			
			BufferedImage bimg=new BufferedImage(w,h,BufferedImage.TYPE_INT_ARGB);
			Graphics2D G=(Graphics2D)bimg.getGraphics();
			
			G.setColor(new Color(r,g,b,255));
			
			G.fillRect(0,0,w,(h>>1)-rad);
			G.fillRect(0,(h>>1)-rad,(w>>1)-rad,2*rad);
			G.fillRect((w>>1)+rad,(h>>1)-rad,(w>>1)-rad,2*rad);
			G.fillRect(0,(h>>1)+rad,w,(h>>1)-rad);
			
			double dg=1;
			for(int i=-rad; i<=rad; i++)
				for(int j=-rad; j<=rad; j++)
				{
					double d=Math.sqrt(i*i+j*j);
					if(d>rad)
					{
						G.setColor(new Color(r,g,b,255));
						G.fillRect((w>>1)+i,(h>>1)+j,1,1);
					}else if(Math.abs(d-rad)<dg)
					{
						double gap=Math.abs(d-rad);
						int op=(int)((1.0-gap/dg)*255.0);
						G.setColor(new Color(r,g,b,op));
						G.fillRect((w>>1)+i,(h>>1)+j,1,1);
					}
				}
			
			G.dispose();
			
			return bimg;
		}
	}
}

Open in new window

0

Experts Exchange Solution brought to you by ConnectWise

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
 
Thomas4019Author Commented:
Awesome code, very cool. This is better than i was even asking for. Customizable feathering!  Thanks.
0
 
Thomas4019Author Commented:
Wow, that second code really is impressive.
0
 
InteractiveMindCommented:
I just discovered that it's possible to perform clipping with Graphics2D, so thought I'd add this link here:
http://www.exampledepot.com/egs/java.awt/ClipShape.html?l=rel

(Unfortunately however, it does not seem to support antialiasing)
0
 
Thomas4019Author Commented:
Interesting, clipping would be useful. The Shape class has always mystified me. I understand how to use it. But how does the Java Graphics methods and others actually use the Shape? The only method that Graphics2D could use to efficiently draw Shapes would be Shape's getPathIterator() unless each method uses instanceof to figure out which Shape it is.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.