# ImageIcon über Socket schicken (Serialisierung)



## Stefan0001 (16. Sep 2012)

Hey Leute


Habe ein kleines Problem:

Ich will mehrere Object über ein Socket senden.
Die Objecte beinhalten:
Zahlen (int)
Text (String)
Bilder (javax.swing.ImageIcon)
Datum (java.sql.Timestamp)
Uhrzeiten (java.sql.Time)

z.B:

```
public class Event extends ListValue implements Serializable{
    private static final long serialVersionUID = 123456789123456789L;
    
    public String name;
    public Timestamp datum;
    public Time dauer;
    public String text;
    public ImageIcon bild
    
    public Event(int id, String name, Timestamp datum, Time dauer, String text, ImageIcon bild){
        super(id);
        this.name = name;
        this.datum = datum;
        this.dauer = dauer;
        this.text = text;
        this.bild = bild;
    }
}
```


So nun habe ich ein Problem bei der Serialisierung.  Wie ihr seht habe ich bereits der Klasse eine serialVersionUID verpasst.  Nun kommt bei einem Freund von mir die Fehlermeldung:

```
java.io.InvalidClassException: javax.swing.ImageIcon; local class incompatible: stream classdesc serialVersionUID = -962022720109015502, local class serialVersionUID = 532615968316031794
```

Wie muss ich den die ImageIcon Klasse erweitern um sie übertragen zu können.
Oder soltle ich eine andere Klasse verwenden.
Meine idee wäre so etwas:

```
import javax.swing.ImageIcon;

public class Bild extends ImageIcon{
    private static final long serialVersionUID = 123456789123456789L;
    
}
```
scheint aber auch nicht wirklich zu funktionieren.

Achja:
Auf dem Server läuft Linux mit JRE 6.0 - bei dem Client läuft Win7 und JRE 7.0
Habe die serialVersionUID nur bei den Objuecten gesetzt die per Socket übertragen werde.
Achja bei meinem Versuch 
	
	
	
	





```
public class Bild extends ImageIcon
```
 habe ich später das Bild einem ImageIcon zugewiesen:  

```
Event e;
ImageIcon i = e.bild;
```

-> e.bild vom Typ Bild
-> Bild erweitert ImageIcon
-> Event e wurde vom Server geschickt


Hoffe mir kann jemand helfen

Mfg


----------



## SlaterB (17. Sep 2012)

welche Java-Versionen hast du auf beiden Seiten?
System.out.println(System.getProperty("java.version"));

ach ja
> Auf dem Server läuft Linux mit JRE 6.0 - bei dem Client läuft Win7 und JRE 7.0
ungünstig eben

ImageIcon (Java Platform SE 7 )


> Warning: Serialized objects of this class will not be compatible with future Swing releases. The current serialization support is appropriate for short term storage or RMI between applications running the same version of Swing. As of 1.4, support for long term storage of all JavaBeansTM has been added to the java.beans package. Please see XMLEncoder.



-----

ein ImageIcon bietet sich aber anscheinend sowieso nicht zur Übertragung an, das Image-Attribut ist als transient markiert,
übertrag eher das herausgeholte Image-Objekt,
noch eher eine simple Datei von der Festplatte, falls das Bild so vorhanden ist, als byte[]


----------



## Stefan0001 (17. Sep 2012)

> übertrag eher das herausgeholte Image-Objekt,


meinst du als awt.Image? 
Dieses lässt sich aber nicht serialisieren (glaub ich)

dann müsste ich ja eine wrapper klassen benutzen oder?


----------



## kaetzacoatl (17. Sep 2012)

dann halt nicht


----------



## SlaterB (17. Sep 2012)

@kaetzacoatl
ist das eine verunglückt formuliere Hilfe?
ansonsten besser eigenen Thread aufmachen..

------

> dann müsste ich ja eine wrapper klassen benutzen oder? 

was soll denn das IconImage dazu machen, sicher verpacken wie ein Koffer für die Flugreise?
nene, das passt hier nicht, eher muss man durch die Wand immer noch bohren auch wenn man ein Holzregal davor stellt 

mein Vorschlag wie gesagt eine Datei als byte[], oder ein BufferedImage malen, das ist auch noch am ehesten in byte[] zu übertragen


edit:
ich sehe aber gerade dass ImageIcon an sich doch geeignet wäre 
How to best serialize a java.awt.Image? - Stack Overflow

das Image-Objekt ist transient, wird nicht direkt serialisiert, eben wohl weil nicht direkt gedacht,
dafür schreiben Methoden die Daten einzeln, also durchaus ein Koffer, aber mit dem Verfahren welches ich eher andachte, 50/50 Recht behalten 

vielleicht helfen dir diese Methoden für eine eigene Übertragung, aus meinem Java 1.5 kopiert:

```
private void writeObject(ObjectOutputStream s) 
	throws IOException 
    {
	s.defaultWriteObject();

	int w = getIconWidth();
	int h = getIconHeight();
	int[] pixels = image != null? new int[w * h] : null;

        if (image != null) {
	    try {
	        PixelGrabber pg = new PixelGrabber(image, 0, 0, w, h, pixels, 0, w);
	        pg.grabPixels();
	        if ((pg.getStatus() & ImageObserver.ABORT) != 0) {
		    throw new IOException("failed to load image contents");
	        }
	    }
	    catch (InterruptedException e) {
	        throw new IOException("image load interrupted");
	    }
        }
    
	s.writeInt(w);
	s.writeInt(h);
	s.writeObject(pixels);
    }

    private void readObject(ObjectInputStream s)
	throws ClassNotFoundException, IOException 
    {
	s.defaultReadObject();
    
	int w = s.readInt();
	int h = s.readInt();
	int[] pixels = (int[])(s.readObject());

        if (pixels != null) {
	    Toolkit tk = Toolkit.getDefaultToolkit();
	    ColorModel cm = ColorModel.getRGBdefault();
	    image = tk.createImage(new MemoryImageSource(w, h, cm, pixels, 0, w));
	    loadImage(image);
        } 
    }
```


----------



## Stefan0001 (17. Sep 2012)

ALSO:

Ich Speicher die Bilder nun als ByteArray wie von dir vorgeschlagen.
Die Objecte enthalten nun ByteArray welche später zu ImageIcons gemacht werden.
Habe mir dafür 2 Methoden gemacht

imageToByteArray      für das laden
 byteArrayToImage    Vor das speichern auf dem server


```
public static byte[] imageToByteArray(ImageIcon img) {
        try {
            BufferedImage buImg = new BufferedImage(img.getIconWidth(), img.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
            buImg.getGraphics().drawImage(img.getImage(), 0, 0, null);
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            ImageIO.write(buImg, "PNG", byteArrayOutputStream);

            return byteArrayOutputStream.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }

    public static ImageIcon byteArrayToImage(byte[] image) {
        try {
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(image);
            BufferedImage buImg = ImageIO.read(byteArrayInputStream);
            return new ImageIcon(buImg);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }
```

mich würde es trotzdem noch interessieren wie das mit dem ImageIcon funktioniert
Hier steht ja das man es für als wrapper bneutzen kann
How to best serialize a java.awt.Image? - Stack Overflow

mfg Stefan


----------



## SlaterB (17. Sep 2012)

ImageIcon ist einfach nicht für Speicherung zwischen verschiedene Versionen vorgesehen, hab ja auch weiter oben aus der API zietiert,
hier wahrscheinlich grundlos, es hat sich nichts geändert,
aber um das zu unterstützen müste man sich mit etwas Aufwand darum kümmern, 
und wenn bei dieser Klasse, dann vielleicht auch bei 1000 anderen, schon wird viel Arbeit daraus,

wobei diese zwecks Übertragung von Bildern, schließlich gibt es extra write + read-Methode, schon prädestiniert wäre,
nein, ich kann das eigentlich nicht begründen, technisch gehts nicht, warum ist mir unklar,
außer wiederum dass in der API ja auf irgendwas verwiesen wird, XMLEncoder, vielleicht geht das allgemein


----------

