2011-09-29 1 views
15

Я хочу сделать изображение с закругленными углами. Изображение будет поступать со входа, и я сделаю его закругленным углом, затем сохраните его. Я использую чистую java. Как я могу это сделать? Мне нужна функция какКак сделать закругленное угловое изображение в Java

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

Schema

Edit: Добавлено изображение информации.

+0

Вы должны быть более конкретными в отношении закругленных углов: Прозрачный или заполненный цветом фона (первый, вероятно, заставит PNG в качестве выходного формата)? Фиксированный или переменный радиус, если последний относительно чего? –

+0

Я предполагаю, что на это был дан ответ: http://stackoverflow.com/questions/1826665/round-corners-on-images-using-java-and-jai – Kris

+0

В этом вопросе отсутствует много необходимой детали, что затрудняет ответ. –

ответ

26

Я предлагаю этот метод, который принимает изображение и производит изображение и сохраняет изображения IO вне:

Edit: я, наконец, удалось сделать Java2D мягкой клип графики с помощью 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 image

Гадкий, зубчатый выход с setClip():

jagged with setclip

Ницца, гладкий выход с композитным трюка:

smooth with composite trick

Крупным планом углов на сером фоне (setClip(), очевидно, слева, композитный справа):

closeup corners on gray bacjground

+0

Углы сглажены, и нет очевидного 'RenderingHint' делает то, что я хочу ... Я обновлю свой код, если Я нахожу способ сделать гладкие углы. –

+0

вам нужно создать четыре Линии и Круги и поместить их в общей сложности, положить здесь Пустые поля и пространство внутри углов перерасчитать за пиксель и удалить это, но зачем изобретать whell для этого есть официальный API – mKorbel

+0

@mKorbel Зачем покупать Swing для простая задача Java2D? Даже если это решит проблему сглаживания, это будет чрезмерное ИМХО. Вышеприведенный код работает, минус точки стиля для псевдонимов. –

0

Я нашел другой способ, используя 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 для каждой краски. (Или, по крайней мере, я еще не нашел лучшего решения для этого.)

2

Я пишу следующее до Ответ Филиппа Рейхарта. ответ как ответ.

Чтобы удалить белый фон (кажется, черный в изображениях), изменить g2.setComposite(AlphaComposite.SrcAtop); к g2.setComposite(AlphaComposite.SrcIn);

Это было большой проблемой для меня, потому что у меня есть разные изображения с прозрачностью, что я не хочу терять ,

Мой оригинальный образ:
enter image description here

Если я использую g2.setComposite(AlphaComposite.SrcAtop);:
enter image description here

Когда я использую g2.setComposite(AlphaComposite.SrcIn); фон является прозрачным.

Смежные вопросы