如何在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()
明显左,复合右):
我正在写下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。 (或者至少我还没有找到更好的解决方案。)