Как сделать закругленное угловое изображение в Java
Я хочу сделать изображение с закругленными углами. Изображение будет поступать со входа, и я сделаю его закругленным углом, затем сохраните его. Я использую чистую java. Как я могу это сделать? Мне нужна функция типа
public void makeRoundedCorner(Image image, File outputFile){
.....
}
![Schema]()
Изменить: добавлено изображение для информации.
Ответы
Ответ 1
Я предлагаю этот метод, который принимает изображение и создает изображение и сохраняет изображение IO снаружи:
Изменить: Наконец-то мне удалось сделать Java2D soft-clip графикой с помощью Java 2D Trickery: 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, 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"));
}
Это то, что имеет вид ввода/вывода описанного выше метода:
Input:
![input image]()
Ужасный, неровный вывод с setClip()
:
![jagged with setclip]()
Хороший, гладкий выход с композитным трюком:
![smooth with composite trick]()
Закройте углы на сером фоне (setClip()
очевидно левый, составной справа):
![closeup corners on gray bacjground]()
Ответ 2
Я пишу следующий ответ Philipp Reichart.
ответ как ответ.
Чтобы удалить белый фон (кажется, что это черное изображение), измените g2.setComposite(AlphaComposite.SrcAtop);
до g2.setComposite(AlphaComposite.SrcIn);
Это была большая проблема для меня, потому что у меня разные образы с прозрачностью, которые я не хочу потерять.
Мое первоначальное изображение:
![введите описание изображения здесь]()
Если я использую g2.setComposite(AlphaComposite.SrcAtop);
:
![введите описание изображения здесь]()
Когда я использую g2.setComposite(AlphaComposite.SrcIn);
, фон прозрачен.
Ответ 3
Я нашел другой способ, используя 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 для каждой краски. (Или, по крайней мере, я пока не нашел лучшего решения для этого.)