如何在Java中创建圆角图像

我想制作一个圆角的图像。 图像将来自输入,我将使其圆角然后保存。 我使用纯java。 我怎样才能做到这一点? 我需要一个像这样的function

public void makeRoundedCorner(Image image, File outputFile){ ..... } 

架构

编辑 :添加了图像以供参考。

我建议这种方法拍摄图像并生成图像并将图像IO保持在外面:

编辑:我终于设法在Java 2D Trickery的帮助下使Java2D软剪辑图形: Chris Campbell的Soft Clipping 。 遗憾的是,这不是Java2D支持开箱即用的一些RenderhingHint

 public static BufferedImage makeRoundedCorner(BufferedImage image, int cornerRadius) { int w = image.getWidth(); int h = image.getHeight(); BufferedImage output = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = output.createGraphics(); // This is what we want, but it only does hard-clipping, ie aliasing // g2.setClip(new RoundRectangle2D ...) // so instead fake soft-clipping by first drawing the desired clip shape // in fully opaque white with antialiasing enabled... g2.setComposite(AlphaComposite.Src); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setColor(Color.WHITE); g2.fill(new RoundRectangle2D.Float(0, 0, w, h, cornerRadius, cornerRadius)); // ... then compositing the image on top, // using the white shape from above as alpha source g2.setComposite(AlphaComposite.SrcAtop); g2.drawImage(image, 0, 0, null); g2.dispose(); return output; } 

这是一个测试驱动程序:

 public static void main(String[] args) throws IOException { BufferedImage icon = ImageIO.read(new File("icon.png")); BufferedImage rounded = makeRoundedCorner(icon, 20); ImageIO.write(rounded, "png", new File("icon.rounded.png")); } 

这就是上面方法的输入/输出:

输入:

输入图像

使用setClip()丑陋,锯齿状输出:

与setclip混在一起

很好,流畅的输出与复合技巧:

顺利的复合技巧

关闭灰色背景上的角落( setClip()明显左,复合右):

在灰色bacjground的特写镜头角落

我正在写下Philipp Reichart的回答。 作为答案的答案。

要删除白色背景(图片中似乎是黑色),请更改g2.setComposite(AlphaComposite.SrcAtop);g2.setComposite(AlphaComposite.SrcIn);

这对我来说是个大问题,因为我有不同的透明图像,我不想丢失。

我原来的形象:
在此处输入图像描述

如果我使用g2.setComposite(AlphaComposite.SrcAtop);
在此处输入图像描述

当我使用g2.setComposite(AlphaComposite.SrcIn); 背景是透明的。

我发现使用TexturePaint另一种方法:

  ImageObserver obs = ...; int w = img.getWidth(obs); int h = img.getHeight(obs); // any shape can be used Shape clipShape = new RoundRectangle2D.Double(0, 0, w, h, 20, 20); // create a BufferedImage with transparency BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D bg = bi.createGraphics(); // make BufferedImage fully transparent bg.setComposite(AlphaComposite.Clear); bg.fillRect(0, 0, w, h); bg.setComposite(AlphaComposite.SrcOver); // copy/paint the actual image into the BufferedImage bg.drawImage(img, 0, 0, w, h, obs); // set the image to be used as TexturePaint on the target Graphics g.setPaint(new TexturePaint(bi, new Rectangle2D.Float(0, 0, w, h))); // activate AntiAliasing g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // translate the origin to where you want to paint the image g.translate(x, y); // draw the Image g.fill(clipShape); // reset paint g.setPaint(null); 

如果您有一个非动画图像,通过仅创建一次BufferedImage并为每个绘制保留它,可以简化此代码。

如果你的图像是动画的,你必须在每个画面上重新创建BufferedImage。 (或者至少我还没有找到更好的解决方案。)