How to Serialize an Object That Includes Bufferedimages

How to serialize an object that includes BufferedImages

make your ArrayList<BufferedImage> transient, and implement a custom writeObject() method. In this, write the regular data for your ImageCanvas, then manually write out the byte data for the images, using PNG format.

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));
}
}
}

Serializing an object that includes BufferedImages

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)));
    }
    }

Is It possible to Serialize an ArrayList of objects that contains a BufferedImage as one of the object's private instance variables in java?

yes u can, and why not?! but we will follow un-straight method and it worked fine with me

  1. it's known that primitive types and array of primitive types are all Serializable
  2. it's also known that we can convert a buffered image instance to a byte array and the inverse is also applicable
  3. so instead of serializing a buffered image we will serialize a byte array that represents this buffered image

I have created a demo that simulate your question

import java.awt.image.*;
import java.io.*;
import javax.imageio.ImageIO;
public class Member implements Serializable
{

private String name;
private byte[] imagebytes;

public Member(String name, BufferedImage image) throws IOException
{
this.name = name;
this.setImage(image);
}

public Member(String name, File imageFile) throws IOException
{
this.name = name;
this.setImage(imageFile);
}

public final void setImage(BufferedImage image) throws IOException
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ImageIO.write(image, "jpg", outputStream);
this.imagebytes = outputStream.toByteArray();
}

public final void setImage(File imageFile) throws IOException
{
BufferedImage bufferedImage = ImageIO.read(imageFile);
this.setImage(bufferedImage);
}

public BufferedImage getImage()
{

try
{
return ImageIO.read(new ByteArrayInputStream(imagebytes));
} catch (Exception io)
{
return null;
}
}

public String getName()
{
return name;
}

}

you can add methods as u like and customize this class as u need
i hope this answer is useful

Correct way to send BufferedImage in object with serialization. writeObject readObject

Your writeObject never writes to out. It writes to the ByteArrayOutputStream which is not used later

UPDATE
See e.g. the post how list of images is serialized. You can skip the count writing/reading

Serialize Obj with 2 BufferedImage transient fields, second image won't be read

The documentation for ImageIO.read states that the InputStream argument is wrapped in an ImageInputStream.

ImageInputStream is not the same as an InputStream. I don’t think you can safely assume that it only reads as far as it needs to; it may read ahead farther, for caching purposes, or perhaps in order to know what to return from its length() method.

In other words, after reading the first image, your InputStream may not be pointing to the exact byte where the second image starts.

One solution to this is to write byte arrays, rather than writing image data directly. The disadvantage is that it’s not scalable; if you have very large images, keeping them in memory will be a performance issue.

public class Person implements Serializable {

// ...

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

if (firstImage != null) {
ByteArrayOutputStream b = new ByteArrayOutputStream();
ImageIO.write(firstImage, "png", b);

out.writeInt(b.size());
b.writeTo(out);

System.out.println("First image saved.");
} else {
out.writeInt(0);
}

if (secondImage != null) {
ByteArrayOutputStream b = new ByteArrayOutputStream();
ImageIO.write(secondImage, "png", b);

out.writeInt(b.size());
b.writeTo(out);

System.out.println("Second image saved.");
} else {
out.writeInt(0);
}
}

private void readObject(ObjectInputStream in)
throws IOException,
ClassNotFoundException {
in.defaultReadObject();

int length = in.readInt();
if (length > 0) {
byte[] bytes = new byte[length];
in.readFully(bytes);
firstImage = ImageIO.read(new ByteArrayInputStream(bytes));
}

length = in.readInt();
if (length > 0) {
byte[] bytes = new byte[length];
in.readFully(bytes);
secondImage = ImageIO.read(new ByteArrayInputStream(bytes));
}
}

}

As a side note, IOException and ClassNotFoundException should not be caught inside the serialization methods. They belong in the throws clause of the method declaration. You don’t want your class pretending that serialization was successful when it didn’t actually succeed, after all. The details of the serialization methods’ signatures are described in the documentation for Serializable.

Serializing/Deserializing buffered images

Edit:Problem solved

Ended up converting the buffered images to a byte array then stuck them in a hash map and used some hash codes as keys.
Then serialized the hash map.
All good.

bufferedImage error while serializing and deserializing objects in Java

SOLVED: the problem was with class "test" in which I had used BufferedImage. the reason I got that error even tough I'd commented that part, was that before commenting that part, I had once run the program and as I was trying to deserialize that already made file, I encountered the error.

Serializing an ArrayList of Objects with BufferedImages

This was answered in the comments so I'll repost it here to close the question.

Mark the attributes you do not want to serialize as transient. V.g., private transient BufferedImage alienImage;. – SJuan76

Write to disk an object that contains a BufferedImage

Solved. It involved some other data that I didn't include in the code that I showed above. Your guys' comments helped me realize what the problem was, though.

It turns out that the BufferedImage there visible wasn't the problem at all. I had a pointer to another object which ALSO contained a BufferedImage, and it was that other BufferedImage (nested in another object) that was causing the OutputStream to throw its exception.

Moral of the story: ObjectOutputStream will serialize even deeply nested objects.



Related Topics



Leave a reply



Submit