# Bilddaten serialisieren



## jf (21. Jan 2011)

Hallo, ich habe eine Konfigurations-Objekt, welches für Persitenz serialisiert wird.
In dem Objekt soll auch ein Bild abgelegt werden. Um den Aufwand zu umgehen und parallel zur Serialisierung noch die Bilddatei abzuspeichern, wollte ich gern fragen, ob es eine Möglichkeit gibt, die Bilddaten über die Serialisierung mit in die XML-Datei zu schreiben.
Kann mir hierzu jemand einen Tipp geben?


----------



## JohannisderKaeufer (21. Jan 2011)

Das Bild kannst du ja als ByteArray einlesen. Dieses kannst du dann mit einem Base64 De/Encoder in einen base64 String umwandeln und dann einfach in einem XML-Feld unterbringen

Java ist auch eine Insel – 4.6 Zeichenkodierungen

Zeigt wie das mit dem Encoder geht.

Mit diesem Verfahren kann man z.B. auch Bilder direkt in einer Html-Seite unterbringen. So dass man nur eine html-Datei hat, in der die Bilder schon integriert sind.

Inline-Grafiken in HTML


----------



## jf (21. Jan 2011)

Danke für den Tipp Johannis!

Ich habe dazu gleich noch eine Frage: wie bekomme ich aus dem ByteArray ein Bild-Objekt, ohne es vorher auf die Festplatte zu speichern - dies wäre ja irgendwie ineffizient.

Edit:
Ich habe gerade bemerkt, dass die Bibliothek für die Base64-Klasse recht groß ist (38MB) und dadurch das ganze Programm auf die fünfache Größe aufblähen würde. Gibt es evtl. Alternativen hierzu?
Oder könnte ich einfach nur die entsprechende Klasse aus der jar extrahieren (dies wäre natürlich nur eine Notlösung!).

Noch ein Nachtrag:
Wo bekomme ich die Bibliothek überhaupt her? Bei findjar hänge ich irgendwie in einer Endlosschleife:
rt.jar - JAR Search - findJAR.com
Bei Sun/Oracle lande ich nur auf der Haupseite und die Suche nach rt.jar bringt nicht viel nützliches...


----------



## JohannisderKaeufer (21. Jan 2011)

ByteArray => Image
Das könnte man mit dem ByteArrayInputStream lösen.

ByteArray => ByteArrayInputStream == Inputstream => Image



Benutzt du commens-codec aus dem Apache-Projekt?

Ich hab mal geschaut, die commons-codec-1.4-bin(2,5mb) aus der du nur das commons-codec-1.4.jar(56,8kb) brauchen solltest, hat irgendwie nichts mit 38 MB zu schaffen.

In diesem Commons-codec gibt es auch noch die Klasse Base64InputStream, die dir einen InputStream liefern sollte.


----------



## JohannisderKaeufer (21. Jan 2011)

Ich hab mal ein kleines Beispiel gemacht, das die Bibliothek apache commons-codec-1.4 nutzt.

Es wird ein Bild geladen, angezeigt, dann in einen Base64Codierten String umgewandelt, der String ausgegeben und aus dem String wieder ein neues Bild erstellt, das angezeigt wird.


```
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;

import org.apache.commons.codec.binary.Base64;
public class ImageTransformation{
	
	private static BufferedImage toBufferedImage(Image src) {
        int w = src.getWidth(null);
        int h = src.getHeight(null);
        int type = BufferedImage.TYPE_INT_RGB;  // other options
        BufferedImage dest = new BufferedImage(w, h, type);
        Graphics2D g2 = dest.createGraphics();
        g2.drawImage(src, 0, 0, null);
        g2.dispose();
        return dest;
    }

	public static void main(String[] args) throws FileNotFoundException, IOException{
		Image image = ImageIO.read(new FileInputStream(new File("probescan.jpeg")));
		
		JOptionPane.showConfirmDialog(null, new Object[]{new JLabel("Image 1"),new JLabel(new ImageIcon(image))});
		
		Base64 b64 = new Base64();
		
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		
		BufferedImage bi = toBufferedImage(image);
		
		ImageIO.write(bi, "jpeg", bos);

		//Das ist der Base64 codierte String der das Bild repräsentiert
		String imageAsBase64 = b64.encodeToString(bos.toByteArray());
		
		System.out.println(imageAsBase64);		
		
		//Ab hier wird aus dem String wieder ein Bild erstellt.		
		byte[] nArray = b64.decode(imageAsBase64);
		
		Image image2 = Toolkit.getDefaultToolkit().createImage(nArray);
		
		JOptionPane.showConfirmDialog(null, new Object[]{new JLabel("Image 2"),new JLabel(new ImageIcon(image2))});
	}
}
```


----------



## jf (21. Jan 2011)

Vielen Dank Johannis, die 38MB hatte ich von findjar - in dem Beispiel, welches du mir als erstes verlinkt hast wurde die Bibliothek rt.jar in com.sun/jars verwendet. Diese scheint so groß zu sein.

Ich hatte das reine Speichern in der XML-Datei bereits hinbekommen, aber dein Code-Beispiel hat mir gleich noch ein paar gute Tipps für das Arbeiten mit Bildern gegeben. - Also nochmal Danke! :toll:


PS:
Eine letzte Frage hätte ich dann doch noch: wie bekomme ich aus einem Image ein byteArray zurück? - Also die Umkehrfunktion von:

```
Toolkit.getDefaultToolkit().createImage(picData);
```


----------



## JohannisderKaeufer (21. Jan 2011)

jf hat gesagt.:


> PS:
> Eine letzte Frage hätte ich dann doch noch: wie bekomme ich aus einem Image ein byteArray zurück? - Also die Umkehrfunktion von:
> 
> ```
> ...



Sollte eigentlich im Beispiel alles enthalten sein.
Zusammengefaßt:

```
private static BufferedImage toBufferedImage(Image src) {
        int w = src.getWidth(null);
        int h = src.getHeight(null);
        int type = BufferedImage.TYPE_INT_RGB;  // other options
        BufferedImage dest = new BufferedImage(w, h, type);
        Graphics2D g2 = dest.createGraphics();
        g2.drawImage(src, 0, 0, null);
        g2.dispose();
        return dest;
}
...
 ByteArrayOutputStream bos = new ByteArrayOutputStream();
        
 BufferedImage bi = toBufferedImage(image);
       
  ImageIO.write(bi, "jpeg", bos);

  byte[] picData = bos.toByteArray()
```

ImageIO schreibt in einen OutputStream, genauergesagt ein ByteArrayOutputStream, der wiederum eine Funktion toByteArray hat. ImageIO benötigt allerdings ein BufferedImage/RenderedImage, da es mit Image allein nichts anfangen kann.


----------



## jf (22. Jan 2011)

Alles klar, da es über drei Ecken geht, hatte ich das nicht gleich erkannt.

In deinem Quelltext gibt es die Zeile

```
int type = BufferedImage.TYPE_INT_RGB;  // other options
```

Heißt das, dass einigen Bildern an dieser Stelle etwas anderes stehen müsste?

Beziehungsweise: Könnte es rein theoretisch vorkommen, dass wenn ich ein Bild lade, es als Image darstelle und dann wieder in ein ByteArray umwandle, um es zu speichern, dieses unter Umständen anders abgespeichert wird, als das Original?


----------

