Serializing an object that includes BufferedImages

痞子三分冷 提交于 2019-12-19 04:49:13

问题


As the title suggests, I'm trying to save to file an object that contains (among other variables, Strings, etc) a few BufferedImages.

I found this: How to serialize an object that includes BufferedImages

And it works like a charm, but with a small setback: it works well if your object contains only ONE image.

I've been struggling to get his solution to work with more than one image (which in theory should work) but each time I read the file in, I get my object back, I get the correct number of images, but only the first image actually gets read in; the others are just null images that have no data in them.

This is how my object looks like:

 class Obj implements Serializable
    {
transient List<BufferedImage> imageSelection= new ArrayList<BufferedImage>();
     // ... other vars and functions

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

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

    }

This is how I'm writing and reading the object to and from a file:

// writing
try (
              FileOutputStream file = new FileOutputStream(objName+".ser");
              ObjectOutputStream output = new ObjectOutputStream(file);
            ){
              output.writeObject(myObjs);
            }  
            catch(IOException ex){
              ex.printStackTrace();
            }

// reading
try(
                    FileInputStream inputStr = new FileInputStream(file.getAbsolutePath());
                    ObjectInputStream input = new ObjectInputStream (inputStr);
                    )
                    {myObjs = (List<Obj>)input.readObject();}
                catch(Exception ex)
                    {ex.printStackTrace();}

Even though I have a list of objects, they get read in correctly and each element of the list is populated accordingly, except for the BufferedImages.

Does anyone have any means of fixing this?


回答1:


The problem is likely that ImageIO.read(...) incorrectly positions the stream after the first image read.

I see two options to fix this:

  • Rewrite the serialization of the BufferedImages to write the backing array(s) of the image, height, width, color model/color space identifer, and other data required to recreate the BufferedImage. This requires a bit of code to correctly handle all kinds of images, so I'll skip the details for now. Might be faster and more accurate (but might send more data).

  • Continue to serialize using ImageIO, but buffer each write using a ByteArrayOutputStream, and prepend each image with its byte count. When reading back, start by reading the byte count, and make sure you fully read each image. This is trivial to implement, but some images might get converted or lose details (ie. JPEG compression), due to file format constraints. Something like:

    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
        out.writeInt(imageSelection.size()); // how many images are serialized?
    
        for (BufferedImage eachImage : imageSelection) {
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
            ImageIO.write(eachImage, "jpg", buffer);
    
            out.writeInt(buffer.size()); // Prepend image with byte count
            buffer.writeTo(out);         // Write image
        }
    }
    
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
    
        int imageCount = in.readInt();
        imageSelection = new ArrayList<BufferedImage>(imageCount);
        for (int i = 0; i < imageCount; i++) {
            int size = in.readInt(); // Read byte count
    
            byte[] buffer = new byte[size];
            in.readFully(buffer); // Make sure you read all bytes of the image
    
            imageSelection.add(ImageIO.read(new ByteArrayInputStream(buffer)));
        }
    }
    


来源:https://stackoverflow.com/questions/32094497/serializing-an-object-that-includes-bufferedimages

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!