# Bilder effizient speichern/serialisieren



## marioschluse (1. Feb 2013)

Hallo Leute,

nachdem ich nun mit Hilfe Bilder in mein Java Projekt anzeigen konnte,
stellt sich das nächste problem:

Ich hab Objekte, die eine ArrayList<Image> enthalten.
Wenn ich diese Objekte realisiere, entsteht eine viele größere Datei, als die Bilder
alle zusammen eigentlich haben sollten....

Wie kann man effizienter Objekte mit Bildern abspeichern?

Vielen Dank


----------



## Marco13 (1. Feb 2013)

Vermutlich beziehst du dich mit der "Größe, die die Bilder eigentlich haben sollten" auf die Größe einer JPG- oder PNG-Datei. Ein Bild der Größe w*h belegt aber mindestens w*h*4 bytes (kannst ja mal schauen, ob das etwa hinkommt). Abilfen: Bilder als JPG oder PNG speichern, oder die Daten noch Zippen (was aber (ggf. deutlich) weniger bringen würde)


----------



## marioschluse (1. Feb 2013)

Ja, das mit der Berechnung hat hin.
Als JPG abspeichern möchte ich vermeiden.
Weil ein Objekt evt. sehr viele Bilder haben könnte...

In google hab ich etwas von BufferArray gelesen.
Hat jemand damit erfahrung?
Dauert dafür das umwandeln von BufferArray zu BufferdImage und dann zu Image nicht lange???


----------



## Marco13 (1. Feb 2013)

Was soll "BufferArray" denn sein? 
Tatsächlich ist es schwer, vorherzusagen, was schneller ist
- Ein 5 MB großes Bild als reine Daten schreiben oder
- Ein 5 MB großes Bild mit JPG auf 500kb runterrechnen und DIE dann schreiben.


----------



## Guybrush Threepwood (2. Feb 2013)

Du könntest die Bilder in byte-Arrays umwandeln und diese serialisieren. Ich habe das einmal bei einem Programm gemacht, das viele kleine PNGs verwendete. Die entstehende Datei war etwa 40% kleiner als der Platz, den die PNGs auf der Platte eigenommen haben. Ich habe das aber eher aus kosmetischen Gründen gemacht, um nicht so viele Einzeldateien zu haben. Hier ein bisschen Code zum Serialisieren und Deserialisieren:


```
/**Serialize array of BufferedImages to file
	 * @param file
	 * @param images
	 * @throws IOException
	 * @throws ClassNotFoundException
	 */
	public static void serializeImages(String file, String[] images) throws IOException, ClassNotFoundException{
		ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file));
		byte[] imageInByte;
		for(int i = 0; i < images.length; i ++){
			BufferedImage originalImage = ImageIO.read(new File(images[i]));
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			ImageIO.write(originalImage, "png", baos);
			baos.flush();
			imageInByte = baos.toByteArray();
			baos.close();
			out.writeObject(imageInByte);
		}
		out.close();
	}
```

Die Funktion liest die Dateien (Übergabe in Form eines String-Arrays) von der Platte und speichert sie in eine Datei.


```
/**Retrieve list of images from serialized image file
	 * @param file
	 * @return ArrayList with BufferedImages
	 * @throws IOException
	 * @throws ClassNotFoundException
	 */
	public static ArrayList<BufferedImage> deserializeImage(String file) throws IOException, ClassNotFoundException{
		ArrayList<BufferedImage> imageList = new ArrayList<BufferedImage>();
		FileInputStream fs = new FileInputStream(file);
		ObjectInputStream in = new ObjectInputStream(fs);
		boolean eof = false;
		try {

			while (!eof) {
				byte[] b = (byte[])in.readObject();
				InputStream in2 = new ByteArrayInputStream(b);
				imageList.add(ImageIO.read(in2));
				in2.close();
			}
		} catch (EOFException e) {
			eof = true;
		}

		in.close();
		fs.close();

		return imageList;
	}
```

(Ja, ich weiß, man sol nicht ArrayList verwenden und stattdessen eine List zurück geben; ist mir aber egal bei meinem Anwendungszweck). Also nun noch einmal richtig: Die Funktion liest die serialisierte Datei ein und gibt die Bilder als ArrayList<BufferedImage> zurück.

Vielleicht nützt es Dir etwas.


----------



## marioschluse (3. Feb 2013)

Ups,
ich meinte natürlich Byte-Array XD

Vielen Dank für dein Code, mir geht's nämlich auch um "kosmetischen" Gründen.
Ich werd dein Code die Tage auf jedenfall ausprobieren ^^


----------



## Spacerat (3. Feb 2013)

@GuyBrush: Und wieso dieser Aufwand mit ImageIO? Bilddatei in ein Bytearray lesen und ByteArray serialisieren. ImageIO wird so erst beim Deserialisieren notwendig. Der Nachteil aber wäre, dass sich dann evtl. auch andere Bildtypen (oder ähnlich Wildes) in dem ObjectStream befinden könnten. Z.B. auch GIFs, die gleich aus mehreren Bildern bestehen könnten.
BTW.: Was haltet ihr vom Multiple-Image Network Graphics Fileformat? Wär's nicht schön, wenn es dafür auch einen Writer gäbe? Ich finde immer nur 'nen Reader.


----------



## Marco13 (4. Feb 2013)

[ot]
Hat von MNG und APNG ( Animated Portable Network Graphics ? Wikipedia ) eigentlich schon ein Format "gewonnen"?
[/ot]


----------



## Spacerat (4. Feb 2013)

[ot]





Marco13 hat gesagt.:


> Hat von MNG und APNG ( Animated Portable Network Graphics ? Wikipedia ) eigentlich schon ein Format "gewonnen"?


Was heisst gewonnen? Ist etwa Krieg? APNG erfreut sich bereits eines weiter reichenden Supports als MNG, ist nur leider nichts Offizielles. Frage mich, warum sich die PNG-Group so wehement dagegen wehrt, diese zusätzlichen Tags in ihr Format aufzunehmen. Die Begründung, für Animationen ein eigenes Format haben zu wollen, ist doch hirnrissig (bedeutet letztendlich nur mehr Arbeit für mich ). Den Beweis dafür liefert wohl MNG-VLC... dass ich nicht Lache. Datentypen wachsen nunmal mit ihren Versionsnummern. Mir würde dabei im übrigen ein einziger Datentyp, den man um was auch immer erweitert, vollkommen ausreichen. Aber nee... jeder Hinz und jeder Kunz macht's anders und das gilt für das Erstellen einer neuen Ansammlung von Bitfolgen (Datentyp) ebenso wie für die dafür existierenden Reader und Writer.[/ot]


----------



## Marco13 (4. Feb 2013)

[ot]





Spacerat hat gesagt.:


> Was heisst gewonnen? Ist etwa Krieg?


Ja, so ähnlich. Du kennst ja vielleicht xkcd: Standards  Wenn jetzt z.B. alle großen Browser nur noch das (animierte) Bildformat XXX unterstützen (blöder Name, ja,  aber...) dann wird sich kaum noch jemand für YYY interessieren....
[/ot]


----------



## Spacerat (4. Feb 2013)

[OT]Ich kenn' zwar das Problem, aber die Karikatur nicht. Aber genau das ist meiner Meinung nach der der falsche Ansatz. Es ist nichts gegen neue Formate einzuwenden, solange sie etwas neues bieten. Bestehende Formate in ein neues standardisierteres Format pressen zu wollen, ist hirnrissig. Kein Mensch wird die neuen Formate lesen können, wenn kein Reader dafür vorhanden ist (BTW.: das ist Standard :lol. Ebenso ist es willkommen, wenn bestehende Formate in ihren Versionsnummern aufsteigen, um zukünftig neuere Technologien zu unterstützen, man bräuchte dann nur noch die Reader geringfügig ändern (BTW.: wusstest du, dass man für z.B. RIFF-WAVE, AIFF, 8SVX und AVI prinzipiell die selben Lesemechanismen verwenden kann? Aber neee, RIFF-WAVE ist - bzw. war es damals zumindest - was neues von MS und hat mit EA-IFF recht wenig zu tun. :bloed. Dann noch die Sache mit den Lizenzgebühren für wirklich neue Sachen. Wie soll das gehen? "Ihr macht unser neues Format zum Standard und bezahlt uns dafür."? :bloed: Und dann ständig diese Fragen (nicht zuletzt hier im Forum): "Wie kann ich Datei N in Umgebung Q verwenden?" die Antwort darauf müsste demnach lauten: "Gar nicht! Diese Trottel, die dieses wunderbar 'neue' Format entwickelten, haben an seiner Verbreitung (Etablierung) eigentlich gar kein Interesse, weil sie Lizenzgebühren erheben. Nimm ersatzweise eines dieser Millionen Standardformate oder wechsle die Umgebung, achte aber darauf, dass Umgebung und Format kompatibel sind." :bloed: Krieg sieht anders aus, da gibt's Gewinner und Verlierer. Diese Konstellation hier aber ist reiner Bullshit, denn es gewinnt keiner. Standards setzt der Anwender - zumindest sollte es so sein.[/OT]


----------

