2013-02-25 15 views
12

Próbuję utworzyć prosty program do edycji obrazów w java. Zrobiłem obiekt ImageCanvas, który zawiera wszystkie informacje dotyczące edytowanego obrazu (niektóre podstawowe właściwości, listę zastosowanych efektów, listę warstw BufferedImage itp.) I chciałem prosty sposób na zapisanie go na dysku, aby może zostać ponownie otwarty później.Jak serializować obiekt, który zawiera BufferedImages

Doszedłem do wniosku, że korzystanie z interfejsu Java Defualt Serializable może być dokładnie tym, czego szukałem i mógłbym napisać cały obiekt do pliku i ponownie wczytać go do pamięci później. Jednak ImageCanvas zawiera ArrayList<BufferedImage> i BufferedImage nie można szeregować (wszystko inne jest).

wiem, że to jest możliwe, aby zastąpić metody writeObject() i readObject(), ale nigdy nie uczyniły i zastanawiałem się, czy jest jakiś prosty sposób na Java serializacji wszystko i mieć trochę niestandardowy sposób do odczytu/zapisu BufferedImage na dysk? Czy jest jakiś inny sposób, aby z łatwością zapisać cały obiekt ImageCanvas na dysku, który przeoczyłem? W końcu mogę zaimplementować mój własny niestandardowy typ pliku obrazu, ale na razie chciałem szybko i łatwo zapisać pliki tymczasowo podczas testowania (klasa ImageCanvas zmieni się bardzo, więc nie chciałem aktualizować mój niestandardowy typ pliku, zanim go sfinalizuję).

Odpowiedz

23

przekształcić swój ArrayList<BufferedImage> przejściowy i zaimplementować niestandardową metodę writeObject(). W tym celu należy zapisać zwykłe dane do ImageCanvas, a następnie ręcznie zapisać dane bajtów dla obrazów, korzystając z formatu PNG.

class ImageCanvas implements Serializable { 
    transient List<BufferedImage> images; 

    private void writeObject(ObjectOutputStream out) throws IOException { 
     out.defaultWriteObject(); 
     out.writeInt(images.size()); // how many images are serialized? 
     for (BufferedImage eachImage : images) { 
      ImageIO.write(eachImage, "png", out); // png is lossless 
     } 
    } 

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 
     in.defaultReadObject(); 
     final int imageCount = in.readInt(); 
     images = new ArrayList<BufferedImage>(imageCount); 
     for (int i=0; i<imageCount; i++) { 
      images.add(ImageIO.read(in)); 
     } 
    } 
} 
+0

jak mogę z niego korzystać. metody są prywatne. – avicennasoftwarelabs

+1

@avicennasoftwarelabs, Po prostu implementacja metody writeObject i readObject spowoduje, że serializacja Java będzie korzystać z tych metod podczas serializowania/deserializacji obiektu, nawet jeśli metody są prywatne. –

+2

Niestety, dekoder PNG w ImageIO ma w nim błędy, co oznacza, że ​​dane, które odsyłasz, nie są tym samym, co dane, które zapisujesz (kolory są często wyłączone przez 1) – mjaggard

0

Serializacja jest dość prosta, ponieważ utrzymuje dane statyczne. Jesteś inaczej we właściwym miejscu, używając obiektu do odczytu/zapisu w rodzinie metod szeregowania. Pomyśl, czym jest "BufferedImage". Jest to buforowana implementacja przesyłania strumieniowego. Aby przekształcić do postaci szeregowej, dane muszą zostać przepłukane do statycznego obiektu, takiego jak tablica bajtów [], a następnie, ŻE obiekt może być przekształcany do postaci szeregowej/deserializowany do/z obrazu buforowanego tak, że buforowane przesyłanie strumieniowe przychodzi/wychodzi z tego bajtu [] szyk.

+0

mógłbyś podać jakiś kod, aby pokazać, jak to będzie w rzeczywistości odbywa się w mojej sytuacji (jak można włączyć BufferedImage do byte [] i jak można włączyć, że z resztą serializacji ImageCanvas)? – scaevity

+0

Postępuj zgodnie z metodami na BufferedImage (jeśli musisz używać tej klasy) odnoszących się do konstruktorów. Z tego można użyć WritableRastra (i innych danych) do utworzenia obrazu BufferedImage. BufferedImage ma metodę getWritableTile (x, y), która zwraca WritableRaster. Klasa Raster, z której WritableRaster jest dziedziczona, ma różne metody getPixel(), które mogą zwracać na przykład tablicę prymitywnych int []. To nie jest strasznie proste, ale można go odwrócić, aby przejść od prymitywów z powrotem do BufferedImage. Rozważ także użycie innej podstawowej klasy obrazu, która jest łatwiejsza do serializowania/deserializacji. –

Powiązane problemy