# Bild drehen



## flflfl (13. Mai 2010)

Hallo,

ich versuche ein Bild zu drehen - schaffe es aber nicht korrekt. Das neue Bild ist immer etwas verschoben (bzw. abgeschnitten - da verschoben)

Mein Code: 

```
public class Rotate extends JPanel {

    BufferedImage img;

    Rotate() {
        try {
            img = ImageIO.read(new File("c:\\test1.jpg"));
        } catch (Exception e) {
            System.err.println("Fehler beim lesen");
        }
    }

    public void paintComponent(Graphics g) {
        //Original zeichnen
        g.drawImage(img, (this.getWidth() - img.getWidth()) / 2, (this.getHeight() - img.getHeight()) / 2, this);

        BufferedImage ret = rot();
        g.drawImage(ret, (this.getWidth() - ret.getWidth()) / 2, (this.getHeight() - ret.getHeight()) / 2, this);

    }

    public BufferedImage rot() {
        double degree = Math.toRadians(45);

        //New Dimensionen weil gedrehtes Bild mehr Platz benötigt
        int newW = (int) (img.getWidth() * Math.sin(degree) + img.getHeight() * Math.cos(degree));
        int newH = (int) (img.getHeight() * Math.cos(degree) + img.getWidth() * Math.sin(degree));

        BufferedImage ret = new BufferedImage(newW, newH, BufferedImage.TYPE_INT_ARGB);

        //AffineTransform drehen
        AffineTransform tx = new AffineTransform();
        tx.rotate(degree, (double) (img.getWidth() / 2), (double) (img.getHeight() / 2));

        //AffineTransform Operation ausführen
        AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
        op.filter(img, ret);

        return ret;
    }
}
```

Danke für eure Hilfe!


----------



## mabuhay (14. Mai 2010)

Verwende folgenden Code um ein Bild zu drehen:


```
if (rotateAngleCurrent >= 360) {
			rotateAngleCurrent = rotateAngleStep;
		} else {
			rotateAngleCurrent += rotateAngleStep;
		}

		newImg = new BufferedImage(iUpdate.getIconWidth(), iUpdate.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
		g2d = newImg.createGraphics();

		//rotate with the anchor point as the mid of the image
		affineTransform.rotate(-Math.toRadians(rotateAngleStep), iUpdate.getIconWidth()/2, iUpdate.getIconHeight()/2);
	  	//Draw the rotated image
		g2d.drawImage(iUpdate.getImage(), affineTransform, null);
```

Sehe gerade ist ja etwas das gleiche wie deine Lösung 

Um wieviel wird das Bild denn abgeschnitten oder verschoben? evtl. nur um 1 pixel? Wenn ja könnte es davon kommen dass du eine integer-Zahl durch 2 dividierst. Da kann schon mal .5 herauskommen was dann natürlich abgeschnitten wird.

mfg


----------



## flflfl (14. Mai 2010)

nein, es ist viel mehr verschoben:






ich habe noch vor dem degree ein Minus eingefügt (wie in deinem Beispiel) brachte aber nichts.

```
public BufferedImage rot() {
        double degree = Math.toRadians(45);

        //New Dimensionen weil gedrehtes Bild mehr Platz benötigt
        int newW = (int) (img.getWidth() * Math.sin(degree) + img.getHeight() * Math.cos(degree));
        int newH = (int) (img.getHeight() * Math.cos(degree) + img.getWidth() * Math.sin(degree));

        BufferedImage ret = new BufferedImage(newW, newH, BufferedImage.TYPE_INT_ARGB);

        //AffineTransform drehen
        AffineTransform tx = new AffineTransform();
        tx.rotate(-degree, img.getWidth() / 2, img.getHeight() / 2);

        //AffineTransform Operation ausführen
        AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
        op.filter(img, ret);

        return ret;
    }
```


----------



## André Uhres (14. Mai 2010)

Versuch's mal so:

```
import java.awt.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import javax.swing.*;
public class Rotate extends JPanel {
    private BufferedImage img;
    private double degree = Math.toRadians(20);
    Rotate() {
        try {
            img = ImageIO.read(new File("c:\\test1.jpg"));
        } catch (Exception e) {
            System.err.println("Fehler beim lesen");
        }
    }
    @Override
    public Dimension getPreferredSize() {
        Dimension dim = super.getPreferredSize();
        //New Dimensionen weil gedrehtes Bild mehr Platz benötigt
        dim.width = (int) (img.getHeight() * Math.sin(degree) + img.getWidth() * Math.cos(degree));
        dim.height = (int) (img.getHeight() * Math.cos(degree) + img.getWidth() * Math.sin(degree));
        return dim;
    }
    @Override
    public void paintComponent(final Graphics g) {
        //Original zeichnen
        g.drawImage(img, (this.getWidth() - img.getWidth()) / 2, (this.getHeight() - img.getHeight()) / 2, this);
        //mit Drehung zeichnen:
        rot(g.create());
    }
    public void rot(final Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        int w = img.getWidth();
        int h = img.getHeight();
        int x = (this.getWidth() - w) / 2;
        int y = (this.getHeight() - h) / 2;
        //center of rotation is center of the Image:
        int xRot = x + w / 2;
        int yRot = y + h / 2;
        //rotate:
        AffineTransform rotation = g2d.getTransform();
        rotation.rotate(degree, xRot, yRot);
        //draw Image with rotation:
        g2d.setTransform(rotation);
        g2d.drawImage(img, x, y, w, h, this);
        g2d.dispose();
    }
    public static void main(final String args[]) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                JFrame f = new JFrame();
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.add(new Rotate());
                f.pack();
                f.setLocationRelativeTo(null);
                f.setVisible(true);
            }
        });
    }
}
```


----------



## flflfl (17. Mai 2010)

Hallo,

mit deinem Beispiel funktioniert es perfekt - aber warum bei mir nicht? Bin beim verzweifeln...


----------



## mabuhay (17. Mai 2010)

Könnte es sein dass das Bild _ret_ halt grösser ist als das Bild _img_ und daher deine Koordinaten nicht mehr stimmen? In deinem Bild sieht es so aus, als wäre der Mittelpunkt gerade um den vergrösserten Bereich verschoben.

André Uhres zeichnet das Original-Bild und berechnet die Koordinaten für das gedrehte Bild separat.


----------



## flflfl (21. Mai 2010)

Ich weiß, dass es irgendwo an den Koordinaten liegt, jedoch will ich es unbedingt mit den AffineTransform hinbekommen.

Mein Code jetzt: (Bild ist nun absichtlich nicht zentriert um weitere Fehlerquellen auszuschließen)

```
int newW = (int) (img.getWidth() * Math.sin(degree) + img.getHeight() * Math.cos(degree));
            int newH = (int) (img.getHeight() * Math.cos(degree) + img.getWidth() * Math.sin(degree));

            BufferedImage ret = new BufferedImage(newW, newH, BufferedImage.TYPE_INT_ARGB);

            //rotate:
            AffineTransform rotation = new AffineTransform();
            rotation.translate((newW - img.getWidth()) / 2, (newH - img.getHeight()) / 2);
            rotation.rotate(degree, (newW - img.getWidth()), (newH - img.getHeight()));

            AffineTransformOp op = new AffineTransformOp(rotation, AffineTransformOp.TYPE_BICUBIC);
            ret = op.filter(img, null);

            int x = 0;
            int y = 0;

            g.drawImage(ret, x, y, this);

            g.setColor(Color.red); //Rund um das gedrehte Bild einen roten Rahmen zeichnen, damit man die Dimensions des Bildes zieht
            g.drawRect(x, y, ret.getWidth(), ret.getHeight());
```

bringt dieses Ergebnis:


----------



## mabuhay (24. Mai 2010)

Jetzt siehst du ja am roten Rahmen dass etwas mit den Dimensionen des gedrehten Bildes nicht stimmt. ein wenig zu hoch und zu wenig breit.
Die Drehung scheint ja OK zu sein da es so aussieht wie wenn es sich um den Mittelpunkt dreht. Könnte es vielleicht noch sein dass dein Panel oder was es auch immer ist einfach zu klein ist und darum ein paar Sachen abgeschnitten werden? Irgendwie ist die Ecke nummer 3 ja am linken Fensterrand abgeschnitten. Sehe sonst nichts verdächtiges...


----------



## flflfl (27. Mai 2010)

Hallo,

tja das mit den Dimensionen scheint so, aber ich habe es nachgerechnet und es sollte eigentlich passen...

Die Dimension des OriginalQuadrats: 300x300px
Die Dimension des neuenQuadrats ("roter Rahmen"): 424x424px

Ich habe das ganze so berechnet: 




Neue Höhe ist dann h1 + h2, neue Breite = l1 + l2

Wenn ich es mit den Lehrsatz des Pytagoras nachrechne, komme ich zum gleichen Ergebnis: QuadratWurzel aus (300² + 300²) = 424,26.

Also sollten die Dimensionen auf alle Fälle stimmen.

lg 

p.s. hab gerade gesehen, dass im obigen Beispiel einmal bei der Berechnung der neuen Dimensionen getWidth() und getHeight() vertauscht sind, sollte aber egal sein, da es ein Quadrat ist.


----------



## mabuhay (27. Mai 2010)

Die Berechnungen zur neuen Grösse sollten schon stimmen, sehe da nichts verdächtiges. 

```
rotation.translate((newW - img.getWidth()) / 2, (newH - img.getHeight()) / 2);
```
Brauchst du diese Zeile überhaupt? Du gibst doch schon bei rotate(...) an um welchen Punkt gedreht werden soll. Irgendwie verschiebst du den Punkt ja nur um 62 Pixel wenn du "(newW - img.getWidth()) / 2" berechnest.
Und versuche mal 

```
rotation.rotate(degree, newW / 2, newH / 2);
```
Ich sehe gerade, das hast du weiter oben ja schon versucht. Dort war das rotierte Bild wenigstens an beiden Ecken gleich abgeschnitten. Bei deinem letzten Post ist es irgendwie ganz an einer komischen Position... Peim Post #3 sieht es einfach so aus wie wenn du es nicht an der richtigen Position wieder zeichnest oder die Transformations-koordinaten falsch sind. verwende bei 

```
tx.rotate(-degree, img.getWidth() / 2, img.getHeight() / 2);
```
statt img.getWidth() und img.getHeight() doch mal newW und newH.

Als Test kannst du mal versuchen mal das BufferedImage nicht mit der neuen Grösse zu erstellen, dann sollten ja alle Ecken gleich abgeschnitten sein.
Ich denke mal mit op.filter(img, ret) wird das Bild gedreht und dann ins neue grössere Bild gezeichnet, aber immer noch mit gleichen x- und y-Koordinaten.

Also: versuche mal den Weg in Post #7 mit den Änderungen von translate() und rotate() die ich dir vorschlage.

mfg


----------

