Trying to convert java.awt.Image to gif file

Hi,

I'm trying to convert a java.awt.Image object to a GIF file.
I follow the example from this site: http://forums.sun.com/thread.jspa?threadID=367004

But it doesn't seem to work. A GIF file generated with file size 0. I'm sure that the Image object is actually available so the GIF image shouldn't have had 0 bytes of data.
How can I solve this problem?

Thanks in advance for all the help.
public void saveGif(Image img, File f){
 
try{
BufferedImage bi = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = bi.createGraphics();
g2d.drawImage(img, 0,0, null);
ImageIO.write(bi, "gif", f);
}
catch(Exception ex){
ex.printStackTrace();
}
}  // end saveGif()

Open in new window

rnicholusAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

CEHJCommented:
gif's not supported by ImageIO ordinarily. png is - which will support transparency
0
rnicholusAuthor Commented:
CEHJ,

Thanks for your reply.

I change the "gif" into "png" type. Still doesn't work. I only got the attached png file (all black).
It's not the expected image result.
testRy.png
0
CEHJCommented:
That suggests 'img' is not valid
0
Learn SQL Server Core 2016

This course will introduce you to SQL Server Core 2016, as well as teach you about SSMS, data tools, installation, server configuration, using Management Studio, and writing and executing queries.

rnicholusAuthor Commented:
CEHJ,

Can you please elaborate?

Thanks.
0
CEHJCommented:
Well there are different ways it can be invalid:


a. it hasn't finished loading.
boolean finishedLoading = g2d.drawImage(img, 0,0, null);

b. The above returns true but the image is essentially 'blank'
0
rnicholusAuthor Commented:
option b is not possible. I have tested the Image object using another approach (using GUI swing).
Let me try option a.
0
rnicholusAuthor Commented:
The finishedLoading returns "false".

How should I handle this?
0
CEHJCommented:
You could use a MediaTracker and add the image to it
0
CEHJCommented:
How are you loading the creating/loading the image in the first place?
0
rnicholusAuthor Commented:
CEHJ,

Can you help me with the coding a little bit how should I use the MediaTracker in the function that I already have?

The last argument in this line of code:
boolean finishedLoading = g2d.drawImage(img, 0,0, null);
is an ImageObserver, right. This is has the same purpose with MediaTracker?

Sorry if this is a newbie questions..

0
CEHJCommented:
>>This is has the same purpose with MediaTracker?

That's right, but in this case would be a litle harder to use


    public void saveGif(Image img, File f){ 
        try{
            BufferedImage bi = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = bi.createGraphics();
            try {
                MediaTracker mt = new MediaTracker(this);
                mt.add(img, 0); 
                mt.waitForAll();
            }   
            catch(InterruptedException e) {
                e.printStackTrace();
            }   
            g2d.drawImage(img, 0,0, null);
            ImageIO.write(bi, "gif", f); 
        }   
        catch(Exception ex){
            ex.printStackTrace();
        }   
    }  // end saveGif()

Open in new window

0
rnicholusAuthor Commented:
CEHJ,

I got this Exception below.
Possibility of using different JDK?
C:\tcprojects\ImageRetrieverTest.java:101: cannot find symbol
symbol  : constructor MediaTracker(com.livewave.api.sample.ImageRetrieverTest)
location: class java.awt.MediaTracker
                MediaTracker mt = new MediaTracker(this);
                                  ^
C:\tcprojects\ImageRetrieverTest.java:102: cannot find symbol
symbol  : method add(java.awt.Image,int)
location: class java.awt.MediaTracker
                mt.add(img, 0); 

Open in new window

0
CEHJCommented:
Ah that would mean you're not in a Component subclass. Again, how do you create the Image in the first place?
0
rnicholusAuthor Commented:
The Image object comes from a 3rd party SDK. Should I give you the code snippet of the Java class I use?
0
CEHJCommented:
That's OK. I'll try something else
0
rnicholusAuthor Commented:
Thanks CEHJ.
0
CEHJCommented:
Try the following as an inner class:
    private class ImageSaver implements ImageObserver {
	private BufferedImage bi = new BufferedImage(200, 200,
		BufferedImage.TYPE_INT_RGB);
	private Image img;
	private File f;
 
	public ImageSaver(Image img, File f) {
	    this.img = img;
	    this.f = f;
	}
 
	public void saveImage(Image img, File f) {
	    try {
		Graphics g = bi.getGraphics();
		g.drawImage(img, 0, 0, this);
	    } catch (Exception ex) {
		ex.printStackTrace();
	    }
	}
 
	public boolean imageUpdate(Image theimg, int infoflags, int x, int y,
		int w, int h) {
	    boolean done = ((infoflags & (ERROR | FRAMEBITS | ALLBITS)) != 0);
 
	    if (done) {
		try {
		    ImageIO.write(bi, "png", f);
		}
		catch (IOException e) {
		    e.printStackTrace();
		}
	    }
	    return !done; //If done, no further updates required.
	}
    }

Open in new window

0
Mick BarryJava DeveloperCommented:
you can use the following to write the image

http://helpdesk.objects.com.au/java/how-do-i-write-a-bufferedimage-to-an-output-stream

Shouldn't be any need to use MediaTracker these days.
0
Mick BarryJava DeveloperCommented:
your problem appears more related to your conversion to a BufferedImage (assuming the original image is valid)
I'd suggest using a JLabel to display the image gotten from the 3rd part, and also the BugfferedImage created to validate they are both ok.

0
rnicholusAuthor Commented:
CEHJ,
I tried your suggestion. It looks like no file created.
I put two System.out.println() statement in imageUpdate() method.

The output of the System.out.println() is:
start of imageUpdate
boolean done: false
start of imageUpdate
boolean done: false

How I use the inner class:
ImageSaver imageSaver = new ImageSaver(image, new File("testRy.png"));      
imageSaver.saveImage();
public boolean imageUpdate(Image theimg, int infoflags, int x, int y,
int w, int h) {
 
System.out.println("start of imageUpdate");       	
boolean done = ((infoflags & (ERROR | FRAMEBITS | ALLBITS)) != 0);
System.out.println("boolean done: " + done);
 
........ // next lines
} // end of imageUpdate() method

Open in new window

0
rnicholusAuthor Commented:
objects,
Yes, perhaps you are right. My problem is to convert it to a BufferedImage object.

I'm not sure is this information helps or not:
Basically I have a 3rd party SDK where it returns an Image object. The ultimate goal is to put the Image up on a Google map in a web-based application.

So my plan is to convert the Image object to a PNG or GIF file to be used by the Google Map application.
0
Mick BarryJava DeveloperCommented:
you don't need an ImageObserver either :)

do the test I suggested above, that will show you where the prob is
and try TYPE_INT_ARGB instead of TYPE_INT_RGB

though a better approach would be to check the color model used by the original image

0
CEHJCommented:
>>
The output of the System.out.println() is:
start of imageUpdate
boolean done: false
start of imageUpdate
boolean done: false
>>

That would suggest that whatever is creating the original image is not doing so correctly
0
rnicholusAuthor Commented:
The 3rd party which SDK I'm using has sample Java code (Swing based app) that has no problem displaying the same Image object created.

objects, can you please clarify which suggestion are you referring to?
package com.livewave.api.sample;
 
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties;
import java.util.Timer;
import java.util.TimerTask;
 
import javax.swing.JFrame;
import javax.swing.JPanel;
 
import com.livewave.api.Camera;
import com.livewave.api.FirstView;
import com.livewave.api.FirstViewContext;
import com.livewave.api.ServiceException;
 
public class ImageRetriever extends JFrame {
 
    private JPanel jContentPane = null;
    private Camera camera = null;
    private Image image = null;
 
    /**
     * @param args
     */
    public static void main(String[] args) {
        ImageRetriever imageRetriever = new ImageRetriever();
        imageRetriever.start();
    }
 
    /**
     * This is the default constructor
     */
    public ImageRetriever() {
        super();
        initialize();
    }
 
    /**
     * This method initializes this
     * 
     * @return void
     */
    private void initialize() {
        this.setSize(320, 240);
        this.setContentPane(getJContentPane());
        this.setTitle("Image Retriever");
    }
    
    /** start the frame */
    private void start() {
        
        // show the frame
        show();
        
        // get the first camera
        camera = getCamera();
        
        // get an Image every 5 seconds
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask(){
            public void run(){
                getImage();
            }
        }, 0, 5000);
    }
    
    /** the main part of the sample getting the image called in response to a mouse click */
    private void getImage(){
 
        // check if there is a camera
        if (camera != null){
            try {
                // get the latest image 
                image = camera.getImage();
            
                // cause it to be painted
                repaint();
            
            } catch (ServiceException e) {
                e.printStackTrace();
            }
        }
    }
 
    /** get the first camera from the server */
    private Camera getCamera() {
        Camera camera = null;
        Properties properties = new Properties();
 
        try {
            InputStream in = new FileInputStream("client.properties");
            properties.load(in);
            in.close();
        }
        catch (Exception e) {
            System.out.println("Not using property file client.properties!");
        }
        
       try {
            String userName = properties.getProperty("UserName", "......"); 
            String password = properties.getProperty("Password", "......"); 
            String dataServerName = properties.getProperty("databaseServerName","......");
            String imageRetrieverCameraID = properties.getProperty("imageRetrieverCameraID","");
    
            System.out.println("Accessing DB at :" + dataServerName);
            
            FirstViewContext firstviewContext = FirstView.createFirstViewContext(dataServerName, userName, password);
 
            if ("".equals(imageRetrieverCameraID)) {
	            Camera[] cameras = firstviewContext.findAllCameras();
	            System.out.println("cameras.length:" + cameras.length);
	            if (cameras.length > 0){
 
	                camera = cameras[30];
	            }
            }
            else {
            	System.out.println("imageRetrieverCameraID: " + imageRetrieverCameraID);
            	camera = firstviewContext.getCamera(imageRetrieverCameraID);
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        
        return camera;
    }
    
    /**
     * This method initializes jContentPane
     * 
     * @return javax.swing.JPanel
     */
    private JPanel getJContentPane() {
        if (jContentPane == null) {
            jContentPane = new JPanel(){
                public void paint(Graphics g) {
                    // check there is an image and paint it.
                    if (image != null) {
                        Rectangle rect = this.getBounds();
                        g.drawImage(image, rect.x, rect.y, rect.width, rect.height, this);
                    }
                }
            };
            jContentPane.setLayout(new BorderLayout());
        }
        return jContentPane;
    }
}

Open in new window

0
Mick BarryJava DeveloperCommented:
> objects, can you please clarify which suggestion are you referring to?

using a ImaheIcon and JLabel to display both the images, that will tell you which step is breaking down.

0
CEHJCommented:
I tested the code i gave you and had the same problem as you - the image never got completely loaded. This was possibly for the same reason - not starting the app in the right thread. It must be started in the EDT. Try it and see if it improves things
    public static void main(String[] args) {
        final String source = args[0];
        final String dest = args[1];
        EventQueue.invokeLater(new Runnable() {
                public void run() {
                    new Gif().saveIt(source, dest);
                }
            });
    }

Open in new window

0
rnicholusAuthor Commented:
Guys,

Thank you for your suggestion. Let's continue next week. Happy memorial day!
0
Mick BarryJava DeveloperCommented:
We use something along the lines of the following code when converting an Image to a BufferedImage.

http://helpdesk.objects.com.au/java/how-to-convert-an-image-to-a-bufferedimage

give it a try and see if it helps

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
CEHJCommented:
You might find the following useful to inspect the flags while you're getting it working:

import java.util.Map;
import java.util.LinkedHashMap;
 
public class ImageObserverBits {
    static Map<Integer, String>  m = new LinkedHashMap<Integer, String>();
    static {
	m.put(1,"WIDTH");
	m.put(2,"HEIGHT");
	m.put(4,"PROPERTIES");
	m.put(8,"SOMEBITS");
	m.put(16,"FRAMEBITS");
	m.put(32,"ALLBITS");
	m.put(64,"ERROR");
	m.put(128,"ABORT");
    }
    public static void main(String[] args) {
	System.out.println(ImageObserverBits.bitsToString(Integer.parseInt(args[0])));
    }
 
    public static String  bitsToString(int imageInfo) {
	StringBuilder sb = new StringBuilder(72);
	for(int i = 1;i < 128;i<<=1) {	
	    if ((imageInfo & i) > 0) {
		if (sb.length() > 0) {
		    sb.append(" | ").append(m.get(i));
		}
		else {
		    sb.append(m.get(i));
		}
	    }
	}
	return sb.toString();
    }
 
}
 
/*
 * public static final int 	ABORT 	128
 * public static final int 	ALLBITS 	32
 * public static final int 	ERROR 	64
 * public static final int 	FRAMEBITS 	16
 * public static final int 	HEIGHT 	2
 * public static final int 	PROPERTIES 	4
 * public static final int 	SOMEBITS 	8
 * public static final int 	WIDTH 	1
 */

Open in new window

0
rnicholusAuthor Commented:
I use this method described in this URL to convert the Image object to BufferedImage object:
http://www.exampledepot.com/egs/java.awt.image/Image2Buf.html

Please see the details in code snippet.
BufferedImage bufferedImage = toBufferedImage(getCameraImage(getCamera(cameraId)));
response.setContentType("image/png");
OutputStream os = response.getOutputStream();
ImageIO.write(bufferedImage, "png", os);
os.close();

Open in new window

0
CEHJCommented:
You *can* do that but it's an unnecessary expense as it creates an unneeded ImageIcon. I've also found several questions on this site where ImageIcon was the source of memory leaks too. I'm not sure if i posted working code, so shall post it after this if not
0
CEHJCommented:
This should be OK if you create the gui in the right thread:
import java.awt.*;
import java.awt.image.*;
 
import java.io.*;
 
import javax.imageio.ImageIO;
 
 
public class PngSaver {
    public static void main(String[] args) {
        final String source = args[0];
        final String dest = args[1];
        EventQueue.invokeLater(new Runnable() {
                public void run() {
                    new PngSaver().saveIt(source, dest);
                }
            });
    }
 
    public void saveIt(String sourceImage, String destImage) {
        Toolkit tk = Toolkit.getDefaultToolkit();
        Image i = tk.createImage(sourceImage);
        ImageSaver imsav = new ImageSaver(i, new File(destImage));
        tk.prepareImage(i, -1, -1, imsav);
    }
 
    private class ImageSaver implements ImageObserver {
        private Image img;
        private File f;
 
        public ImageSaver(Image img, File f) {
            this.img = img;
            this.f = f;
        }
        public boolean imageUpdate(Image img, int infoflags, int x, int y,
            int w, int h) {
            boolean done = ((infoflags & (ERROR | FRAMEBITS | ALLBITS)) != 0);
 
            if (done) {
                try {
		    // Don't need ImageObserver now
		    BufferedImage bi = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_RGB);
		    Graphics g = bi.createGraphics();
		    g.drawImage(img, 0, 0, null); // Don't need ImageObserver now
		    ImageIO.write(bi, "png", f);
		} catch (IOException e) {
		    e.printStackTrace();
		}
	    }
 
	    return !done; //If done, no further updates required.
	}
    }
}

Open in new window

0
Mick BarryJava DeveloperCommented:
> I use this method described in this URL to convert the Image object to BufferedImage object:

that should do the trick, its same as what we use.
How did that go?

0
rnicholusAuthor Commented:
I give points for objects and CEHJ for assisting solution.
Look at 24485987 for what I do.
0
CEHJCommented:
>>Look at 24485987 for what I do.

That will work but see my comments at http:#24486036
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.