Link to home
Start Free TrialLog in
Avatar of gujuraja143
gujuraja143

asked on

Image as an Object

Now I have everything working, but I can't find anything on how to save a image as an object.  Is this possible, if so how do I do this?

I know how to save text as objects, but how do I save an image as an object of a file?

Avatar of allahabad
allahabad

  try {
       

         FileOutputStream ostream = new FileOutputStream("imagestoarge.tmp");
         ObjectOutputStream p = new ObjectOutputStream(ostream);

         p.writeObject(imageObject);
       
         p.flush();
         ostream.close();
      }
      catch(Exception e){
         e.getMessage();
      }
Avatar of Mick Barry
> Is this possible, if so how do I do this?

You cannot save the image object itself.
You can however encode the image using an image format such as jpg, or gif.
Avatar of gujuraja143

ASKER

What do you mean?  I can't save the image as an object?
What exactly is it you are trying to do?
Im trying to save some information about the image and also some other information that I am trying to get from the user.  This information is stored as objects in a file.

The information I can save, but I was wondering if it is possible to save that image also as an object in that file.  So when I need it later, I will be able to open that specific file and it will have the image there and its information.

Thanks
No you can't save your image as an object.
you need to encode the image data as I mentioned above.
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
encoder.encode((BufferedImage)image);


My last question is, after I encode the image into that file, I can still store objects in that file, right?

Will I need to put something in that file to tell what the objects are and what the image is, like a separator?

Thank you again.
You should be ok, but can't say for certain without trying it.
Couldn't you have the image as attribute in the object, like lets say if I am saving different attributes, and one of those attributes is Image, would this be possible?

Like if we wanted to open the object up, the specific attributes will be there.  Will this work? or no?

I am just thinking of different ideas of how to go about doing this.

Thank you again,

I am increasing the points for your troubles
> Couldn't you have the image as attribute in the object

Thats no different than saving the image object directly.
You cannout do it because the Image object is not Serializable.
If you wanted to include the image as an attribute of another object then you could encode the image to a byte array and store that byte arrat as an object attribute.
Byte arrary...How would I change the image to a byte array and then the byte array to the image back again.  

If this works, this would be perfect.

Thank you,

If I get this working, I will increase the points to 500,

Thank you in advance.
Here you go for JPEG encoding:

ByteArrayOutputStream out = new ByteArrayOutputStream();
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
encoder.encode((BufferedImage)image);
out.close();
byte[] data = out.toByteArray();


This is one way of doing this. It looks quite a lot of code, but this is mostly in main, which you can delete once you see how it works. This shows an image, serializes it, along with some properties and then deserializes it and shows it in another window:

import java.io.*;
import java.awt.*;
import java.awt.image.*;
import java.util.Hashtable;

public class ImageWrapper implements Serializable {
  private int[] imageData;
  private Hashtable properties;
  transient private Image image;
  private int imageWidth;
  private int imageHeight;


  public ImageWrapper(Image image) {
    properties = new Hashtable();
    this.image = image;
  }

  public static void main(String[] args) {

    try {
      // Create a test image dynamically
      int width= 200;
      int height = 200;
      final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
      WritableRaster raster = image.getRaster();
      // Make an image of light blue colour
      int[] colour = { 0xcc, 0xcc, 0xff };
      for(int i = 0;i < width;i++) {
        for(int j = 0;j < height;j++) {
          raster.setPixel(i, j, colour);
        }
      }

      // Show image in frame

      javax.swing.JFrame f = new javax.swing.JFrame();

      f.setContentPane(new javax.swing.JPanel() {

        public void paintComponent(java.awt.Graphics g) {
          g.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
        }
      });
      f.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
      f.setSize(300, 300);
      f.setVisible(true);


      // Make an ImageWrapper
      ImageWrapper iw = new ImageWrapper(image);
      // Write a to the;
      iw.setImageWidth(width);
      iw.setImageHeight(height);
      iw.putProperty("Title", "Light blue rectangle image");
      iw.saveImageData();


      // Serialize wrapper data

      // Create temp file
      File temp = File.createTempFile("image", "dat");
      temp.deleteOnExit();
      ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(temp));
      System.out.println("Serializing image data");
      out.writeObject(iw);
      out.close();

      // Deserialize wrapper data

      ObjectInputStream in = new ObjectInputStream(new FileInputStream(temp));
      System.out.println("Deserializing image data");
      ImageWrapper savedImage = (ImageWrapper)in.readObject();
      System.out.println("Reading image wrapper data...");
      System.out.println("Title = " + (String)savedImage.getProperty("Title"));

      // Now recreate image
      int w = savedImage.getImageWidth();
      int h = savedImage.getImageHeight();
      final BufferedImage recreatedImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
      WritableRaster wr = recreatedImage.getRaster();
      wr.setSamples(0, 0, w, h, 0, savedImage.getImageData());


      // Show RECREATED image in frame

      javax.swing.JFrame fNew = new javax.swing.JFrame();

      fNew.setContentPane(new javax.swing.JPanel() {

        public void paintComponent(java.awt.Graphics g) {
          g.drawImage(image, 0, 0, recreatedImage.getWidth(), recreatedImage.getHeight(), null);
        }
      });
      fNew.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
      fNew.setSize(300, 300);
      fNew.setLocation(400, 0);
      fNew.setVisible(true);
    }
    catch(Exception e) {
      e.printStackTrace();
    }

  }

  public void saveImageData() {
    // Create a buffer to hold image data
    int width = image.getWidth(null);
    int height = image.getHeight(null);
    int[] buff = new int[width * height];
    PixelGrabber pg = new PixelGrabber(image, 0, 0, width, height, buff, 0, 1);
    Object data = pg.getPixels();
    //DEBUG
    System.out.println(data);

    // clone the int array
    int[] tmp = (int[])data;
    int sz = tmp.length;
    imageData = new int[sz];
    System.arraycopy(tmp, 0, imageData, 0, sz);

  }

  public void putProperty(Object key, Object value) {
    properties.put(key, value);
  }

  public Object getProperty(Object key) {
    return properties.get(key);
  }

  public int[] getImageData(){
    return this.imageData;
  }


  public void setImageWidth(int imageWidth){
    this.imageWidth = imageWidth;
  }

  public int getImageWidth(){
    return this.imageWidth;
  }


  public void setImageHeight(int imageHeight){
    this.imageHeight = imageHeight;
  }

  public int getImageHeight(){
    return this.imageHeight;
  }


}
Not sure on the accuracy of saving just the pixel data would be as you lose colour model details etc, and it also required 4 bytes per pixel which is quite expensive.

Better to use an appropriate image encoder that meets your needs imo.
I'm not sure about the following:

>>encoder.encode((BufferedImage)image);

(the source may not be a BufferedImage)


and also symmetricality: the source data may not be recoverable after encode/decode

> (the source may not be a BufferedImage)

1. easy to make it one
2. that was simply an encoder example.

> the source data may not be recoverable after encode/decode

Depends on the encoder used. I only supplied jpeg as an example, png or gif could similiarily be used.
Here are a stack of good resources on saving images:
http://www.geocities.com/marcoschmidt.geo/java-image-coding.html
CEHJ, that code somewhat works, but the second time you open the image, shouldnt that be recreatedImage instead of image.

when i did replace that with recreatedImage, it doesn't show the image, it just showes black, everything black.

>>shouldnt that be recreatedImage instead of image.

Yes - you're right.

>>it just showes black, everything black.

Oh dear - i'll try and have a look at it again later
If anyone can help me on this, I am raising the point value to a 1000.

I have tried getting this working, but I can't manage to do this.
I will give the person that gets this answer the 500 other points.
Did you try the code I posted?
What have you tried?
for your code, how would I store that that byte array after I try what you gave me?....I tried doing it but couldnt really figure it out.

also after I do store it as a byte array, how would I recompile the image back again?

thanks.
ASKER CERTIFIED SOLUTION
Avatar of Mick Barry
Mick Barry
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
// loading image then saving it

                  fileName = fileChooser.getSelectedFile().getAbsolutePath();
                   Toolkit toolkit = Toolkit.getDefaultToolkit();
                    image = toolkit.getImage(fileName);
                   
                    MediaTracker mediaTracker = new MediaTracker(new Frame());
                   mediaTracker.addImage(image, 0);
                   mediaTracker.waitForID(0);
                   
                   ByteArrayOutputStream out = new ByteArrayOutputStream();
                    JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
                    encoder.encode((BufferedImage)image);
                    out.close();
                    byte[] data = out.toByteArray();
                   
                    FileOutputStream fout = new FileOutputStream(fileName+".xpg");
                    fout.write(data);



for some weird reason this is giving me an error any clue?


and also after i save this file, and i open a type xpg file, how would I tell java that this file contains a byte array?  or does this line..

Image im = Toolkit.getDefaultToolkit().createImage(data);

do it automatically.  Like lets say I go to my application and say open type .xpg file, and then I open it, would that like automatically do that?

Thanks
// loading image then saving it

                  fileName = fileChooser.getSelectedFile().getAbsolutePath();
                   Toolkit toolkit = Toolkit.getDefaultToolkit();
                    image = toolkit.getImage(fileName);
                   
                    MediaTracker mediaTracker = new MediaTracker(new Frame());
                   mediaTracker.addImage(image, 0);
                   mediaTracker.waitForID(0);
                   
                   ByteArrayOutputStream out = new ByteArrayOutputStream();
                    JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
                    encoder.encode((BufferedImage)image);
                    out.close();
                    byte[] data = out.toByteArray();
                   
                    FileOutputStream fout = new FileOutputStream(fileName+".xpg");
                    fout.write(data);



for some weird reason this is giving me an error any clue?


and also after i save this file, and i open a type xpg file, how would I tell java that this file contains a byte array?  or does this line..

Image im = Toolkit.getDefaultToolkit().createImage(data);

do it automatically.  Like lets say I go to my application and say open type .xpg file, and then I open it, would that like automatically do that?

Thanks
// loading image then saving it

                  fileName = fileChooser.getSelectedFile().getAbsolutePath();
                   Toolkit toolkit = Toolkit.getDefaultToolkit();
                    image = toolkit.getImage(fileName);
                   
                    MediaTracker mediaTracker = new MediaTracker(new Frame());
                   mediaTracker.addImage(image, 0);
                   mediaTracker.waitForID(0);
                   
                   ByteArrayOutputStream out = new ByteArrayOutputStream();
                    JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
                    encoder.encode((BufferedImage)image);
                    out.close();
                    byte[] data = out.toByteArray();
                   
                    FileOutputStream fout = new FileOutputStream(fileName+".xpg");
                    fout.write(data);



for some weird reason this is giving me an error any clue?


and also after i save this file, and i open a type xpg file, how would I tell java that this file contains a byte array?  or does this line..

Image im = Toolkit.getDefaultToolkit().createImage(data);

do it automatically.  Like lets say I go to my application and say open type .xpg file, and then I open it, would that like automatically do that?

Thanks
> this is giving me an error any clue?

Whats the error?

> how would I tell java that this file contains a byte array?  

All files are basically an array of bytes.


// loading image then saving it

                  fileName = fileChooser.getSelectedFile().getAbsolutePath();
                   Toolkit toolkit = Toolkit.getDefaultToolkit();
                    image = toolkit.getImage(fileName);
                   
                    MediaTracker mediaTracker = new MediaTracker(new Frame());
                   mediaTracker.addImage(image, 0);
                   mediaTracker.waitForID(0);
                   
                   ByteArrayOutputStream out = new ByteArrayOutputStream();
                    JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
                    encoder.encode((BufferedImage)image);
                    out.close();
                    byte[] data = out.toByteArray();
                   
                    FileOutputStream fout = new FileOutputStream(fileName+".xpg");
                    fout.write(data);



for some weird reason this is giving me an error any clue?


and also after i save this file, and i open a type xpg file, how would I tell java that this file contains a byte array?  or does this line..

Image im = Toolkit.getDefaultToolkit().createImage(data);

do it automatically.  Like lets say I go to my application and say open type .xpg file, and then I open it, would that like automatically do that?

Thanks
well its not giving the error when i compile the code, it gives me an error when i run the code,

java.lang.ClassCastException
    at Trans.imageChooser(Trans.java:660)

this is basically this line:

encoder.encode((BufferedImage)image);

that line is #660.

Thanks
That would be because you image is not a BufferedImage.

Here's a JPEG encoder that does not require a BufferedImage.
What do you mean?  So what JPEG encoder should I use, or how should I write that?

woops forgot to paste the link :)

http://www.afu.com/jpeg.txt

Which you use is up to you, you can use this one directly with your image, or create a BufferedImage and use Sun's.



                    final Image im = Toolkit.getDefaultToolkit().createImage(data);
final BufferedImage recreatedImage = new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB);
javax.swing.JFrame fNew = new javax.swing.JFrame();

                    fNew.setContentPane(new javax.swing.JPanel() {

                           public void paintComponent(java.awt.Graphics g) {
                             g.drawImage(recreatedImage, 0, 0, im.getWidth(null), im.getHeight(null), null);
                           }
                    });
                         fNew.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
                    fNew.setSize(300, 300);
                    fNew.setLocation(400, 0);
                    fNew.setVisible(true);


OK last question,

I believe it stores the information in a byte array, but I dont know if this is right?  When I open the image, it opens but its all black???  So is there something wrong in my code opening the image?
              ByteArrayOutputStream out = new ByteArrayOutputStream();
                    JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
                    final BufferedImage newimage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
                    encoder.encode((BufferedImage)newimage);
                    out.close();
                    byte[] data = out.toByteArray();

Thats how I make the bufferedImage and store it also...
You do not appear to be painting your image to your newly created image.

Graphics@d g2d = newimage.createGraphics();
g2d.drawImage(image, 0, 0, null);
for some weird reason my compiler cant find Graphics2d?

its saying that it cannot resolve symbol.

I also tried transporting other librarys such as Graphics, and also the Graphics2d library itself??

any reason for this?

wow this is taking a long time.....

thanks for your help, you are probably getting fustrated, but I will make it worth while after I get this working.

Thanks
Justr try:

Graphics g = newimage.createGraphics();
g.drawImage(image, 0, 0, null);
                  fileName = fileChooser.getSelectedFile().getAbsolutePath();
                   Toolkit toolkit = Toolkit.getDefaultToolkit();
                    image = toolkit.getImage(fileName);
                   
                    MediaTracker mediaTracker = new MediaTracker(new Frame());
                   mediaTracker.addImage(image, 0);
                   mediaTracker.waitForID(0);
                   
                   ByteArrayOutputStream out = new ByteArrayOutputStream();
                    JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
                    final BufferedImage newimage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
                    Graphics g = newimage.createGraphics();
                    g.drawImage(image, 0, 0, null);
                    encoder.encode((BufferedImage)newimage);
                    out.close();
                    byte[] data = out.toByteArray();
                   FileOutputStream fout = new FileOutputStream(fileName+".xpg");
                   fout.write(data);
                    fout.close();
                  final Image im = Toolkit.getDefaultToolkit().createImage(data);
                   final BufferedImage recreatedImage = new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB);
                   javax.swing.JFrame fNew = new javax.swing.JFrame();

                    fNew.setContentPane(new javax.swing.JPanel() {

                           public void paintComponent(java.awt.Graphics g) {
                             g.drawImage(recreatedImage, 0, 0, im.getWidth(null), im.getHeight(null), null);
                           }
                    });
                         fNew.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
                    fNew.setSize(300, 300);
                    fNew.setLocation(400, 0);
                    fNew.setVisible(true);




thats all my code for viewing and saving the image...but it's still not working, its still showing all black.

Thanks
Yes, recreatedImage is blank.
Why aren't you just painting 'im'?
ok that works, it stores it in the file.

now last question, right now im opening the image directly right after i create the byte array data.

how would I do it when I choose the file, like right here...im telling the program where exactly the file is located:

File test = new File("C:/test.jpg.xpg");

how would I open that file?

and the points for you will be waiting, im creating the points right now.

Thanks
image = toolkit.getImage(test.getPath());

or

image = toolkit.getImage("C:/test.jpg.xpg");