cropping in image into an cricle

Viewed 117

I want to crop an image which is rectangular , into a circle of specific diameter. I am able to do it through graphics2D, and I get the image saved, but, when I read it through ImagIO, i get the full image again inspite to it being cropped to a circle. the image is a masked circle, and evrything outside is discarded like a mask. I am attaching the image here. inspite of it being clipped, i get the full image rendered, when i read it through imageIO. here is the code.

 int w = bufferedImage.getWidth();
  int h = bufferedImage.getHeight();
  BufferedImage output = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);

  Graphics2D g2 = output.createGraphics();
  Area areaOval = new Area(new Arc2D.Double(0, 0, w, w, 0, 360,
      Arc2D.PIE));
      Shape shapeClipSave = g2.getClip();

      g2.setClip(areaOval);
      g2.drawImage(bufferedImage, 0, 0, null);
      g2.setClip(shapeClipSave);
  bufferedImage=output;
  try {
    ImageIO.write(bufferedImage,"png", new File("D:/new.png"));
    bufferedImage= ImageIO.read(new File("D:/new.png"));
  } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
  }
  g2.dispose();

enter image description here

1 Answers

Here's my take. I rewrote some parts for performance and better fidelity (I couldn't get the edges of the circular area antialiased using clip). Although your code should also work, in general.

public static void main(String[] args) throws IOException {
    BufferedImage image = ImageIO.read(new File(args[0]));

    // Remove odd borders (imgur issue?)... Remove this if your input doesn't have borders
    image = image.getSubimage(10, 0, image.getWidth() - 20, image.getHeight() - 10);

    int w = image.getWidth();
    int h = image.getHeight();

    image = createCircular(image, Math.min(w, h));

    if (!ImageIO.write(image, "png", new File("new.png"))) {
        System.err.println("Could not write PNG format");
        System.exit(1);
    }

    image = ImageIO.read(new File("new.png"));

    showItAll(image);

}

private static BufferedImage createCircular(BufferedImage image, int size) {
    BufferedImage output = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);

    Graphics2D g2 = output.createGraphics();
    try {
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.fillOval(0, 0, size, size);

        g2.setComposite(AlphaComposite.SrcIn);
        g2.drawImage(image, 0, 0, null);
    } 
    finally {
        g2.dispose();
    }
    
    return output;
}

private static void showItAll(BufferedImage image) {
    JFrame frame = new JFrame("test");
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.setContentPane(new JPanel() {
        {
            setBackground(Color.ORANGE);
        }
    });
    frame.getContentPane().add(new JLabel(new ImageIcon(image)));
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
}

Using your giraffe as input, I got the following output, the orange background is just to make the transparent parts clearly visible:

Circular selection of image

Alternatively, if you use the TwelveMonkeys library and the Adobe Path Support module, you can replace:

image = createCircular(image, Math.min(w, h));

with the following:

int size = Math.min(w, h);
image = Paths.applyClippingPath(new Ellipse2D.Float(0, 0, 1, 1), 
                                image.getSubimage(0, 0, size, size));

Just be aware that the shape coordinates are relative to the size of the image, not in pixels.

Related