2011-09-29 13 views
15

Desidero creare un'immagine con gli angoli arrotondati. Un'immagine verrà dall'input e io lo renderò arrotondato, quindi lo conserverò. Io uso puro java. Come lo posso fare? Ho bisogno di una funzione comeCome rendere un'immagine angolare arrotondata in Java

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

Schema

Edit: Aggiunta di un'immagine per le informazioni.

+0

Dovrai essere più specifico sugli angoli arrotondati: trasparente o riempito con un colore di sfondo (il primo probabilmente imporrà il PNG come formato di output)? Raggio fisso o variabile, se quest'ultimo è relativo a cosa? –

+0

Immagino che abbia risposto qui: http://stackoverflow.com/questions/1826665/round-corners-on-images-using-java-and-jai – Kris

+0

Un sacco di dettagli necessari mancano da questa domanda che rende difficile risposta. –

risposta

26

suggerisco questo metodo che prende un'immagine e produce un'immagine e mantiene l'immagine IO esterno:

Edit: sono finalmente riuscito a fare Java2D soft-agganciare la grafica con l'aiuto di Java 2D Trickery: Soft Clipping da Chris Campbell . Purtroppo, questo non è qualcosa che Java2D supporta immediatamente con alcuni 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; 
} 

Ecco un collaudatore:

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")); 
} 

Questo è ciò che l'input/output del metodo di cui sopra appare come:

ingresso:

input image

Ugly, uscita frastagliata con setClip():

jagged with setclip

Nizza, uscita liscio con trucco composito:

smooth with composite trick

Primo piano degli angoli su sfondo grigio (setClip() ovviamente a sinistra, a destra composito):

closeup corners on gray bacjground

+0

Gli angoli sono aliasati, però, e nessun 'RenderingHint' evidente fa quello che voglio ... aggiornerò il mio codice se Trovo un modo per rendere gli angoli smussati. –

+0

devi creare quattro linee e cerchi e metterlo insieme, mettere qui EmptyBorders e lo spazio all'interno degli angoli ricalcolare per pixel e rimuoverlo, ma perché reinventare il whell perché c'è l'API ufficiale – mKorbel

+0

@mKorbel Perché andare Swing per un semplice compito Java2D? Anche se ciò risolva il problema di aliasing, sarebbe eccessivo IMHO. Il codice sopra riportato funziona, meno i punti stile per l'aliasing. –

0

Ho trovato un altro modo utilizzando 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); 

Questo codice può essere semplificata se si dispone di un'immagine non animata, creando la BufferedImage solo una volta e mantenendolo per ogni vernice.

Se l'immagine è animata, è necessario ricreare BufferedImage su ogni vernice. (O almeno non ho ancora trovato una soluzione migliore per questo.)

2

Sto scrivendo un seguito alla risposta Philipp Reichart. la risposta di come risposta.

Per rimuovere lo sfondo bianco (sembra essere nero nelle immagini), cambiare g2.setComposite(AlphaComposite.SrcAtop); a g2.setComposite(AlphaComposite.SrcIn);

Questo è stato un grosso problema per me perché ho diverse immagini di trasparenza che io non voglio perdere .

mia immagine originale:
enter image description here

Se uso g2.setComposite(AlphaComposite.SrcAtop);:
enter image description here

Quando uso g2.setComposite(AlphaComposite.SrcIn); lo sfondo è trasparente.

Problemi correlati