Abrunden der Ecken von Grafiken

Status
Nicht offen für weitere Antworten.

muaddib

Neues Mitglied
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

Gesperrter Benutzer
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

Neues Mitglied
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

Bekanntes Mitglied
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

Top Contributor
Das Stichwort heißt Clipping. Kleines Beispiel dazu:

Code:
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

Bekanntes Mitglied
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

Top Contributor
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

Bekanntes Mitglied
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:


Code:
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
Code:
imageManager.createImage(String Url) aufrufen.
. Wie würde der o.g. Code dann da rein passen? Ich krieg's leider irgendwie nicht hin.
 

Quaxli

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

Code:
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

Bekanntes Mitglied
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

Code:
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

Bekanntes Mitglied
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.

Code:
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!
 
Status
Nicht offen für weitere Antworten.

Ähnliche Java Themen


Oben