# Abrunden der Ecken von Grafiken



## muaddib (28. Apr 2006)

Hallo Leute, 

weiß jemand vielleicht, wie man mittels Java relativ einfach die Ecken einer beliebigen Grafik abrunden kann, gibt es hierzu vielleicht eine einfach Möglichkeit in JAI oder Java2D? 

Danke und viele Grüße 
Muaddib


----------



## L-ectron-X (28. Apr 2006)

Abrunden geht nur mit Transparenz bzw. Pseudotransparenz, wenn die Grafik also den Hintergrund des eben auf dem Monitor gezeigten Bildes erhält.
Was willst du genau machen?


----------



## muaddib (28. Apr 2006)

Der Hintergrund ist weiß, es würde mir also reichen, die abgerundeten Ecken (so in der Art von drawRoundRect) praktisch durch überzeichnen mit weiß zu erstellen. 
Ich habe so gut wie keine Erfahrung mit Java2D und JAI, wie könnte ich sowas am besten bewerkstelligen?


----------



## TSH (3. Okt 2008)

Ich hol den alten Thread hier mal hoch, weil ich ein ähnliches Problem habe.

*Ausgangslage:*
JPG Bilder verschiedener Form und Größe.

*Ziel:*
Quadratische Bilder einheitlicher Größe mit abgerundeten Ecken, wie zB hier: Klick mich

Das ganze soll auf weißem Hintergrund ausgegeben werden. Ich würde gerne ausgehend vom Mittelpunkt des Bildes ein maximales Quadrat ausschneiden, den Bereich auf zB 200x200 Pixel skalieren, die Ecken abrunden und einen Rahmen drum legen.

Ich habe viel Erfahrung mit Java, aber noch nie mit Bildern zu tun gehabt. Kann mir jemand sagen, in welcher Richtung ich suchen soll, um das o.g. zu erreichen?


----------



## Quaxli (3. Okt 2008)

Das Stichwort heißt Clipping. Kleines Beispiel dazu:


```
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;

public class Tes extends JPanel {

	BufferedImage pic;

	public Tes() {
		
		try {
			pic = ImageIO.read(getClass().getClassLoader().getResourceAsStream("pic.jpg"));
		} catch (IOException e) {}
		
		JFrame frame = new JFrame();
		frame.setSize(200,200);
		frame.setLocation(100,100);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.add(this);
		frame.setVisible(true);
	}

	public static void main(String[] args) {
    new Tes();
	}
	
  protected void paintComponent(Graphics g) {   
    super.paintComponent(g);
    g.setClip(new RoundRectangle2D.Double(10,10,pic.getWidth(),pic.getHeight(),10,10));
    g.drawImage(pic,10,10,this);

    g.setClip(new RoundRectangle2D.Double(10,70,pic.getWidth(),pic.getHeight(),10,10));
    g.drawImage(pic,10,70,this);
    
  }
}
```

Wenn das Ganze dynamischer sein soll, mußt Du natürlich ein bißchen mehr Logik rein stopfen, aber obiges Beispiel zeigt einen einfachen Weg, um die Bilder abzurunden.


----------



## TSH (3. Okt 2008)

Danke, ich werd mir das mal anschauen. Letztlich muss ich das Bild aber irgendwie an eine JSP-Seite übergeben, die es dann einbaut.

Wahrscheinlich sollte ich es abspeichern und die URL weitergeben. Aber wie würde ich denn statt der drawImage-Methode das Bild abspeichern können?


----------



## Quaxli (4. Okt 2008)

Statt des Graphics-Objekts des JPanels, legst Du ein BufferedImage an (auf Transparenz achten), holst Dir dessen Graphics-Objekt, zeichnest da rein und speicherst das Ganze mit ImageIO ab.


----------



## TSH (4. Okt 2008)

Hm, danke. Krieg ich leider noch nicht so ganz hin. In meiner Architektur hab ich einen ImageManager, der bei Übergabe einer URL ein quadratisches, abgerundetes Bild erstellen und abspeichern soll.  So in der Art:



```
public class ImageManager {

	public ImageManager(){
		...
	}

	public void createImage(String imageURL) {
		// Bild von URL einlesen
		// Quadratischen Ausschnitt rausschneiden
		// abgerundeten Rahmen drum machen
		// Bild abspeichern.
	}
	
}
```

Der ImageManager wäre auch für's Bilder laden, cachen usw. zuständig. Die o.g. Funktionalität würde ich dann mit 
	
	
	
	





```
imageManager.createImage(String Url) aufrufen.
```
. Wie würde der o.g. Code dann da rein passen? Ich krieg's leider irgendwie nicht hin.


----------



## Quaxli (5. Okt 2008)

Wollen wir mal nicht so sein... ;-)


```
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;

public class Tes extends JPanel {

   BufferedImage pic;

   public Tes() {
      
     
  	  pic = createImage(getClass().getClassLoader().getResource("pic.jpg"));
  	 
      JFrame frame = new JFrame();
      frame.setSize(200,200);
      frame.setLocation(100,100);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.add(this);
      frame.setVisible(true);
   	 
   }
  
  public BufferedImage createImage(URL imageURL) {
  	
  	BufferedImage buf = null;
  	BufferedImage temp = null;
  	
  	try {
			temp = ImageIO.read(imageURL);
		} catch (IOException e) {
      return null;
		}
  	
  	buf = new BufferedImage(temp.getWidth(),temp.getHeight(),BufferedImage.TRANSLUCENT);
  	Graphics drawBuf = buf.createGraphics();
  	
  	drawBuf.setClip(new RoundRectangle2D.Double(0,0,temp.getWidth(),temp.getHeight(),10,10));
  	drawBuf.drawImage(temp, 0, 0, this);
  	drawBuf.dispose();
  	 
  	return buf;
  	
   }
 
  	 

   public static void main(String[] args) {
    new Tes();
   }
   
  protected void paintComponent(Graphics g) {   
    super.paintComponent(g);
    g.drawImage(pic, 10,10,this);
   
  }
}
```


----------



## TSH (5. Okt 2008)

Vielen Dank. Ich hab die Methode *createImage(URL imageUrl)* übernomme,  rätsel aber schon den ganzen Tag an der Skalierung und des Cropping/Clipping (?) auf ein Quadrat.

Da mein ImageManager ja nicht von einem JPanel erbt, würde ich gerne Methoden


```
private void resizeImage(BufferedImage bufImage, int width, int height){
  // Hier sollte einfach nur das Bild skaliert werden.
}

private void cropToSquare(BufferedImage bufImage){
  // Hier sollte ausgehend von der Bildmitte ein maximal mögliches Quadrat ausgeschnitten werden.
}
```

Leider kriege ich es überhaupt nicht hin.    Hast Du (oder jemand anderes) auch diesmal eine gute Idee?


----------



## TSH (5. Okt 2008)

So, ich hab's jetzt mal etwas geordnet.

- getScaledImage soll es skalieren
- getFramedImage soll es mit den runden Ecken einrahmen
- doMagic hat mal alles zusammen gefasst.


```
public void doMagic(String imageURL) throws IOException{
	URL imgUrl = new URL(imageURL);
	BufferedImage image = ImageIO.read(imageURL);
	BufferedImage scaledImage = this.getScaledImage(image, 150, 150);
	BufferedImage framedImage = this.getFramedImage(resizedImage);
	
	File imgFile = fileManager.getFile("myfile.png");
	ImageIO.write(framedImage, "png", imgFile);
}

private BufferedImage getScaledImage(BufferedImage originalImage, int width, int height){
	Image tempImg = originalImage.getScaledInstance(width, height,Image.SCALE_SMOOTH);
	BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
	resizedImage.createGraphics().drawImage(tempImg, 0, 0, null);
	return resizedImage;
}

private BufferedImage getFramedImage(BufferedImage originalImage){
	BufferedImage buf = new BufferedImage(originalImage.getWidth(),originalImage.getHeight(),BufferedImage.TRANSLUCENT); 
	Graphics graphics = buf.createGraphics(); 
	graphics.setClip(new RoundRectangle2D.Double(0,0,originalImage.getWidth(),originalImage.getHeight(),10,10)); 
		      
	graphics.drawImage(originalImage, 0, 0, null); 
	graphics.dispose(); 
	return buf; 		
}
```
Ist leider noch etwas pixelig an den Rändern und die Skalierung ist verzerrt, da noch kein Quadrat ausgeschnitten wird. Aber so langsam komm ich voran. Danke, noch einmal!


----------

