Falsches Ergebnis bei Bildrotation

mac21

Aktives Mitglied
Hallo zusammen,

ich habe ein kleines "Tool" zur Bearbeitung von Bildern (wer mich kennt weiß, dass es sich um Fahrzeugscheine handelt^^) geschrieben.
Ein Funktion ist das Drehen von Bildern.
Diese hab ich in folgender Klasse umgesetzt

Java:
package examples;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class RotateTest extends JPanel {
	
	private BufferedImage image = null;

	public RotateTest(BufferedImage image) {	
		this.setBackground(Color.green);
		if(image != null) {
			setImage(image);
		}
	}
	
	public void setImage(BufferedImage orig) {
		this.image = orig;
	}
	
	 public void rotateImage(double degrees)
	    {
	     BufferedImage blankCanvas = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
	     Graphics2D g2 = (Graphics2D)blankCanvas.getGraphics();
	     g2.rotate(Math.toRadians(degrees), image.getWidth() / 2, image.getHeight() / 2);
	     g2.drawImage(this.image, 0, 0, this);
	     this.image = blankCanvas;
	 }
	
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		if (image != null) {
			g.drawImage(image, 0, 0, this.getWidth(), this.getHeight(), this);
		}
	}
	
	public static void main(String[] args) throws IOException, InterruptedException {
		BufferedImage img = ImageIO.read(new File("C://OCR TEST//1.jpg"));
		JFrame frame = new JFrame();
		//frame.setUndecorated(true);
		frame.setBackground(Color.red);
		frame.setBounds(10,10,400,600);
		RotateTest a = new RotateTest(img);		
		frame.add(a);
		frame.setVisible(true);
		System.out.println("Frame: X="+frame.getWidth()+" Y="+frame.getHeight());
		System.out.println("CP:    X="+frame.getContentPane().getWidth()+" Y="+frame.getContentPane().getHeight());
		System.out.println("Panel: X="+a.getWidth()+" Y="+a.getHeight());
		Thread.sleep(2000);
		frame.setVisible(false);
		frame.remove(a);
		frame.repaint();
		Thread.sleep(2000);
		RotateTest b = new RotateTest(img);
		b.rotateImage(90);
		int newH = frame.getWidth();
		int newW = frame.getHeight();
		frame.setSize(newW, newH);
		frame.add(b);
		frame.setVisible(true);
		System.out.println("Frame: X="+frame.getWidth()+" Y="+frame.getHeight());
		System.out.println("CP:    X="+frame.getContentPane().getWidth()+" Y="+frame.getContentPane().getHeight());
		System.out.println("Panel: X="+b.getWidth()+" Y="+b.getHeight());			
	}
}

Der Code in der main()-Methode ist natürlich gerade nur zum Testen des Ergebnisses.
Die Problematik beim Drehen von Bildern ist ja, dass der Bildinhalt um x Grad gedreht wird, der Rahmen (das rectangle) jedoch nicht. Somit wird das Bild unerwünscht abgeschnitten.

Meine Idee:

Lade ein Bild in ein Fenster mit Breite B und Höhe H.
Soll das Bild um 180 Grad gedreht werden ist alles tip top, krieg ich hin.
Wird es jedoch um 90 oder 270 (= -90) grad gedreht,
so setze ich das Fenster auf nicht sichtbar, entferne das im Code gezeigte JPanel und erzeuge ein neues.
Das Fenster und dieses Panel werden um 90 Grad gedreht, dann wird das Panel ins Fenster gepackt und letzteres wieder sichtbar gemacht.

So sieht das Fenster vor der Drehung aus:
original.png
Jedoch kommt folgendes Ergebnis dabei heraus:
gedreht.png

Dass die FrameDecoration in der gesetzten Höhe einberechnet wird weiß ich, jedoch sieht das Ergebnis auch "undecorated" so aus...
Dann gilt: Vor und Nach der Drehung sind die Werte aus "getWidth()" und "getHeight()" von Frame, dem ContentPane des Frames und des JPanels gleich.
zb: 400/600, nach der Drehung 600/400

Seht ihr wo mein Denkfehler liegt?

Vielen Dank schon einmal!


P.S. Variablen richtig benennen, Formatierung beachten, Spaghetti-Code beseitigen...
Ich weiß ;) hierbei handelt es sich nur um eine Testklasse, um den Vorgang des Drehens zu verstehen.
 
Zuletzt bearbeitet:
A

asc-st

Gast
Servus,

du musst dir die neue Breite/Höhe ausrechnen, ansonsten ist der Drehpunkt und die anschließenden Dimensionen falsch (mit denen du ja rechnen willst).

Habe die 2-Frame Methode mal entfernt und zeichne das Bild einfach neu. Du kannst dir das ja wieder zurechtbasteln.

Hier die Lösung: (mit kleineren Anpassungen)

Java:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class RotateTest extends JPanel {

  private BufferedImage image;

  public RotateTest(BufferedImage image) {
    setBackground(Color.GREEN);
    if (image != null)
      setImage(image);
  }

  public void setImage(BufferedImage image) {
    this.image = image;
  }

  public void rotateImage(double angle) {
    double sin = Math.abs(Math.sin(Math.toRadians(angle)));
    double cos = Math.abs(Math.cos(Math.toRadians(angle)));
    int w = image.getWidth(null);
    int h = image.getHeight(null);
    int neww = (int) Math.floor(w * cos + h * sin);
    int newh = (int) Math.floor(h * cos + w * sin);
    BufferedImage bimg = new BufferedImage(neww, newh, BufferedImage.TYPE_INT_ARGB);
    Graphics2D g = bimg.createGraphics();
    g.translate((neww - w) / 2, (newh - h) / 2);
    g.rotate(Math.toRadians(angle), w / 2, h / 2);
    g.drawRenderedImage(image, null);
    g.dispose();
    this.image = bimg;
  }

  public void paintComponent(Graphics g) {
    super.paintComponent(g);
    if (image != null) {
      int iw = image.getWidth();
      int ih = image.getHeight();
      System.out.println(iw + " -> " + ih + " in " + getWidth() + " -> " + getHeight());
      g.drawImage(image, Math.abs((getWidth() - iw) / 2), Math.abs((getHeight() - ih) / 2), iw, ih, this);
    }
  }

  public static void main(String[] args) throws IOException, InterruptedException {
    BufferedImage img = ImageIO.read(new File("C://TEMP/javapoo.png"));
    RotateTest rot = new RotateTest(img);
    Dimension dim = new Dimension(800, 600);
    JFrame frame = new JFrame();

    frame.setSize(dim);
    frame.setBackground(Color.red);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().setPreferredSize(dim);
    frame.getContentPane().add(rot);
    frame.setVisible(true);
    frame.setLocationRelativeTo(null);
    frame.pack();

    Thread.sleep(1000);
    rot.rotateImage(90);
    frame.repaint();
  }
}

Schönes Wochenende!
 
Zuletzt bearbeitet von einem Moderator:

Ähnliche Java Themen

Neue Themen


Oben