繁体   English   中英

如何在Java中制作圆角图像

[英]How to make a rounded corner image in Java

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

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

架构

编辑:添加了信息图像。

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

编辑:我终于在 Chris Campbell 的Java 2D Trickery: Soft Clipping的帮助下成功地制作了 Java2D 软剪辑图形。 可悲的是,这不是 Java2D 支持的一些RenderhingHint开箱即用的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, i.e. 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()明显左侧,复合右侧):

灰色 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。 (或者至少我还没有找到更好的解决方案。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM