# JPG drehen, skalieren und speichern



## Sandforelle (30. Apr 2008)

Hallo zusammen,

ich bin das erste Mal hier im Forum und hoffe ihr könnt mir helfen.

Ich bin noch dabei Java zu lernen und habe mir das Ziel gesetzt endlich eine lange gewolltes Programm fertig zu bekommen.
Ich will Bilder (JPG) drehen, dann skalieren (verkleinern) und anschließend ohne Kompression speichern. Alles ohne Sie anzuzeigen.
Habe mir dazu auch schon einiges zusammengesucht aber so richtig funktioniert es nicht.

Das drehen des Bildes funktioniert prima.

```
//Bild drehen
	BufferedImage inputImage = ImageIO.read(new File( "C:/IMG_0001.jpg" )); 
    new RotateImage( 90 ); // current Angle
    BufferedImage rotatedImage = rotateImage(inputImage);
    ImageIO.write(rotatedImage,"JPG",new File("C:/rot.jpg"));
    //---------------------
```

Das skalieren nur noch so halb.
Ich bekomme zwar ein Bild mit der richtigen Größe, es ist aber leer (bzw. grau  :bahnhof: ).

```
//Bild skalieren
    BufferedImage scaledImage = new BufferedImage(2048, 3072, BufferedImage.TYPE_INT_RGB);
    Graphics2D g = scaledImage.createGraphics();
    AffineTransform at = AffineTransform.getScaleInstance((double)2048,(double)3072);
    g.drawRenderedImage(rotatedImage,at);
    ImageIO.write(scaledImage,"JPG",new File("C:/rot_skal.jpg"));
    //-----------------------
```

Die dann folgende Einstellung der Kompression funktioniert wieder.
Das endgültig Bild ist dann durch das fehlerhafte Ergebnis der Skalierung ebenfalls leer.

```
//Compression einstellen
    Iterator iterator = ImageIO.getImageWritersBySuffix("jpeg");
    ImageWriter imageWriter = (ImageWriter) iterator.next();
    JPEGImageWriteParam imageWriteParam = new JPEGImageWriteParam(Locale.getDefault());
    imageWriteParam.setCompressionMode(JPEGImageWriteParam.MODE_EXPLICIT);
    imageWriteParam.setCompressionQuality(1.0F);
    
    //Speichern
    IIOImage iioImage = new IIOImage(scaledImage, null, null);
    imageWriter.setOutput(ImageIO.createImageOutputStream(new File("C:/rot_skal_comp.jpg")));
    imageWriter.write(null, iioImage, imageWriteParam);
    //--------------------------------------
```

Habt ihr eine Idee wo es dabei hakt ???

Vielen Dank

Sandforelle


----------



## Marco13 (30. Apr 2008)

AffineTransform at = AffineTransform.getScaleInstance((double)2048,(double)3072);

Lass mich raten: Der obere, linke Pixel deines Bildes ist grau? :wink:
Was dort angegeben ist, sind _Faktoren_, und nicht die gewünschte Zielgröße.

AffineTransform at = AffineTransform.getScaleInstance(2,0.5);
Macht das Bild doppelt so breit und halb so hoch wie vorher.


----------



## Sandforelle (30. Apr 2008)

Eigentlich nicht.

Die Größe des Bildes stimmt.
Es sind 2048*3072 Pixel und alles ist grau.

?????


----------



## The_S (30. Apr 2008)

Warum skallierst du nicht über Image#getScaledInstance?


----------



## Sandforelle (30. Apr 2008)

Weil ich Image.getScaledInstance nicht mit dem BufferedImage zusammenbekomme. ?!


----------



## The_S (30. Apr 2008)

zusammenbekomme? Das Wort in dem Zusammenhang versteh ich net/ist schwammig


----------



## Sandforelle (30. Apr 2008)

Ich arbeite ja überall mit BufferdImage.

Ich habe es nicht hinbekommen ein BufferedImage in ein Image zu ändern und dann Image.getScaledInstance anzuwenden.

Leider hab ich von der ganzen Materie auch nocht nicht so die Ahnung.


----------



## The_S (30. Apr 2008)

Du kannst einfach BufferedImage#getScaledInstance aufrufen. Dazu brauchst du kein Image, da BufferedImage von Image erbt.


----------



## Sandforelle (30. Apr 2008)

OK,

ich habe also ein BufferedImage namens rotatedImage.

```
BufferedImage rotatedImage = rotateImage(inputImage);
```
Dieses will ich nun verkleinern.

Dann schreibe ich den Code mit meinen bescheidenen Kenntnissen um in:

```
int wNew = 2048, hNew = 3072;

	BufferedImage scaledImage = rotatedImage.getScaledInstance(wNew, hNew, BufferedImage.SCALE_SMOOTH);
	BufferedImage outImg = new BufferedImage(wNew, hNew, BufferedImage.TYPE_INT_RGB);
	Graphics g = outImg.getGraphics();
	g.drawImage(scaledImage, 0, 0, null);
	g.dispose();

	
	ImageIO.write(scaledImage,"JPG",new File("C:/rot_skal.jpg"));
```

Allerdings bekomme ich in der Zeile von rotatedImage.getScaledInstance die Meldung, das eine Konvertierung von Image auf BufferedImage nicht möglich ist.

Irgendeine Idee was ich falsch mache ??


----------



## Marco13 (30. Apr 2008)

Sandforelle hat gesagt.:
			
		

> Eigentlich nicht.
> 
> Die Größe des Bildes stimmt.
> Es sind 2048*3072 Pixel und alles ist grau.
> ...


DU hast ein Bild der Größe 2048*3072 Pixel. Und das wird mit den Faktoren 2048 und 3072 skaliert. Was rauskommt, wäre ein Bild der Größe 4 Millionen x 9.4 Millionen. Hm  :?


----------



## Sandforelle (30. Apr 2008)

Ich habe ein Bild mit 2304*3456 Pixel und das ist zu 2048*3072 geworden.

Ich habe mir nach deinem Hinweis die Syntax noch mal angeschaut.
Es sind wirklich Faktoren!
Frag mich bitte nicht wieso das Bild die richtigen Dimensionen hat ?!?!


----------



## Marco13 (30. Apr 2008)

Das BufferedImage, das du erstellst, hat die angegebene Größe. Aber das, was dort _reingezeichnet_ wird, ist mit diesen Faktoren skaliert. D.h. der obere, linke Pixel deines Eingabe-Bildes wird 2048x3072 Pixel groß gezeichnet, und füllt damit den gesamten Bereich des BufferedImages, wo er reingezeichnet wird. Und er IST grau, gell? :wink:


----------



## Sandforelle (30. Apr 2008)

Danke für den Tipp, es funktioniert jetzt :O).

Allerdings sieht das Bild etwas sehr "verpixelt" aus.
Linien sind nicht mehr glatt.

Gibts da noch eine andere Variante das bild zu drehen und zu skalieren eventuelle über das angedeutete BufferdImage.getScaltedInstance anstatt AffinTramsform.

Danke nochmals


----------



## The_S (2. Mai 2008)

Mit getScaledInstance kannst du angeben wie skalliert werden soll (fein, schnell, ...). Du kannst auch erstmal rausfinden ob der Qualitätsverlust am skalieren oder am rotieren liegt.


----------



## Marco13 (2. Mai 2008)

Hier gibt's noch infos und Beidpielcode dazu: http://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html


----------



## Gast (5. Mai 2008)

Vielen Daaaaank !!

Die Tipps haben mich endlich ans Ziel gebracht.

Folgender Code hats gerichtet:

```
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
```

Danke ...


----------

