Please help with my Graphics2D clipping algorithm
I'm trying to write a redeye removal function which has the user click on an image to create a Stack of Circle(s) where the pupils are, then "clips" the circle(s) and applys a RasterOp against the pixels inside the clip. I found an example here (http://java.sun.com/mailers/techtips/corejava/2006/tt0923.html) and modified it to fit my needs. (Code below)
My problem is that it seems like I'm applying the RasterOp filter against the entire source (BufferedImage) and then compositing the result it on top of the source using the alpha channel. This could be a 10MP photo!
How can I make this more efficient by just applying the RasterOp against the Shape(s) which make up the clip? I tried a couple of ways, but I can't figure it out. Is there a better way to do this?
[ filterShape is called frompublicvoid paintComponent( Graphics g )]
publicvoid filterShape(Graphics g, Stack<Rectangle> redeyes){
//Create a translucent intermediate image in which we can perform
//the soft clipping
GraphicsConfiguration gc = ((Graphics2D) g).getDeviceConfiguration();
BufferedImage img = gc.createCompatibleImage(this.getWidth(), this.getHeight(), Transparency.TRANSLUCENT);
Graphics2D g2 = img.createGraphics();
//Clear the image so all pixels have zero alpha
g2.setComposite(AlphaComposite.Clear);
g2.fillRect(0, 0, this.getWidth(), this.getHeight());// sets the background to transparent
//Render our clip shape into the image. Note that we enable
//antialiasing to achieve the soft clipping effect. Try
//commenting out the line that enables antialiasing, and
//you will see that you end up with the usual hard clipping.
g2.setComposite(AlphaComposite.Src);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.WHITE);// sets the mask for opaque
for(int i=0;i<redeyes.size();i++){
Rectangle r = redeyes.elementAt(i);
Ellipse2D.Float circle =new Ellipse2D.Float(r.x, r.y, r.width, r.height);
g2.clip((Shape)circle);
}
g2.fillRect(0, 0, this.getWidth(), this.getHeight());
//Here's the trick... We use SrcAtop, which effectively uses the
//alpha value as a coverage value for each pixel stored in the
//destination. For the areas outside our clip shape, the destination
//alpha will be zero, so nothing is rendered in those areas. For
//the areas inside our clip shape, the destination alpha will be fully
//opaque, so the full color is rendered. At the edges, the original
//antialiasing is carried over to give us the desired soft clipping
//effect.
g2.setComposite(AlphaComposite.SrcAtop);
BufferedImage clipBI = FotoFix.applyRedeyeFix((BufferedImage)this.image);
g2.drawImage(clipBI, 0, 0, this.getWidth(), this.getHeight(),null);
// paint the whole g2 red to see if clip constrains the paint
//g2.setColor(Color.RED); // sets the mask for opaque
//g2.fillRect(0, 0, this.getWidth(), this.getHeight());
g2.dispose();
g.drawImage(img, 0, 0,null);
}
NOTE: The code works for a Stack.size()=1 right now, still debugging to add multiple redeyes to the clip.>

