Saving image to an ObjectOutputStream?

Hi all --

Using JRE 1.5, I'm trying to save an image into the same stream I'm saving a bunch of data to. However, I always get an "OptionalDataException" when I try to read the resulting file. Here's the code:

BufferedImage image =new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);

ObjectOutputStream out =new ObjectOutputStream(new FileOutputStream("testfile.tst"));

ImageIO.write(image,"png", out);

out.writeObject(Color.blue);

out.flush();

out.close();

ObjectInputStream in =new ObjectInputStream(new FileInputStream("testfile.tst"));

image = ImageIO.read(in);

in.readObject();

in.close();

[919 byte] By [catsclawa] at [2007-10-3 4:14:54]
# 1

import java.awt.*;

import java.awt.image.BufferedImage;

import java.io.*;

import javax.imageio.ImageIO;

import javax.swing.*;

public class ObjectOutputTest {

public static void main(String[] args) throws IOException,

ClassNotFoundException {

File file = new File("cougar.jpg");

BufferedImage image = ImageIO.read(file);

ImageIcon icon = new ImageIcon(image);

Color color = Color.blue;

double d = 0.552;

JLabel label = new JLabel(String.valueOf(d), icon, JLabel.CENTER);

String outFile = "objectOutputTest";

ObjectOutputStream out = null;

try {

out = new ObjectOutputStream(

new BufferedOutputStream(

new FileOutputStream(outFile)));

out.writeDouble(d);

out.writeObject(color);

out.writeObject(label);

} finally {

out.close();

}

ObjectInputStream in = null;

try {

in = new ObjectInputStream(

new BufferedInputStream(

new FileInputStream(outFile)));

double dIn = in.readDouble();

Color blueIn = (Color)in.readObject();

JLabel labelIn = (JLabel)in.readObject();

System.out.println("dIn = " + dIn);

System.out.println("blueIn = " + blueIn);

JOptionPane.showMessageDialog(null, labelIn, "results",

JOptionPane.PLAIN_MESSAGE);

} finally {

in.close();

}

}

}

74philipa at 2007-7-14 22:16:21 > top of Java-index,Security,Cryptography...
# 2
That's a cute workaround, but I'm a little leery about using it. The documentation for ImageIcon warns that serialized icons won't be forward-compatible, and I'd like better control about what format to save the image in.
catsclawa at 2007-7-14 22:16:21 > top of Java-index,Security,Cryptography...
# 3

Get the underlying raster and from there you can access the actual raw data:

int[] dstBuffer = ((DataBufferInt) dst.getRaster().getDataBuffer())

.getData();

Then you'll have some binary data to put to the OOS. However, the format of the data may still change between JDK versions.

Another option would be to create a ByteArrayOutputStream and use ImageIO to save that image in some lossless format. Than, put the resulting byte array to your OOS and later on you'll be able to use ImageIO to restore the data from the saved contents.

kirillga at 2007-7-14 22:16:21 > top of Java-index,Security,Cryptography...
# 4
I like the ByteArrayOutputStream idea -- since that should work no matter the version -- but it's causing problems with memory, since some of the graphics are large.Doesn't anyone have any idea why the ImageIO read and write methods are broken?
catsclawa at 2007-7-14 22:16:21 > top of Java-index,Security,Cryptography...
# 5

Hello,

I was able to reproduce your problem. I then tried using "jpg", "gif", and "bmp" as my image formats. I did NOT get the exception when using these.

Perhaps a bug in the PNG reader?

Is this an acceptable workaround? Or do you have to use PNG?

BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);

ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("testfile.tst"));

ImageIO.write(image, "jpg", out); // JPEG works.

out.writeObject(Color.blue);

out.flush();

out.close();

ObjectInputStream in = new ObjectInputStream(new FileInputStream("testfile.tst"));

image = ImageIO.read(in);

in.readObject();

in.close();

nbloma at 2007-7-14 22:16:21 > top of Java-index,Security,Cryptography...