2011-09-29 28 views
15

我想製作一個帶圓角的圖像。圖像將來自輸入,我會使它圓角然後保存。我使用純java。我怎樣才能做到這一點?我需要一個像如何在Java中製作圓角圖像

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

Schema

編輯功能:添加了一個圖像信息。

+0

你需要對圓角更具體:透明或填充背景顏色(第一個可能會強制PNG作爲輸出格式)?固定或可變半徑,如果後者相對於什麼? –

+0

我想這是在這裏回答:http://stackoverflow.com/questions/1826665/round-corners-on-i-i-using-java-and-jai – Kris

+0

很多必要的細節從這個問題缺少,使它很難回答。 –

回答

26

我建議這個方法,它的圖像,併產生圖像,並且保持圖像IO外:

編輯:我終於設法與的Java 2D Trickery: Soft Clipping由克里斯·坎貝爾幫助Java2D的軟夾的圖形。不幸的是,這並不是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'做我想要的...我會更新我的代碼if我找到了一個平滑角落的方法。 –

+0

你必須創建四條線和圓,並把它放在這裏EmptyBorders和空間內的角落重新計算每個像素,並刪除,但爲什麼要重新發明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

我正在寫一個跟進Philipp Reichart的回答。 作爲答案的答案。

除去白色背景(似乎是黑的圖片),改變g2.setComposite(AlphaComposite.SrcAtop);g2.setComposite(AlphaComposite.SrcIn);

這是一個大問題,對我來說,因爲我有,我不希望失去透明度不同的圖像。

我的原始圖像:
enter image description here

如果我使用g2.setComposite(AlphaComposite.SrcAtop);
enter image description here

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