Accessing Animated GIFs with ImageIO

R

Rhino

I've started working with the ImageIO but there is something I don't see in
the API Guide or the API.

Basically, I would like to write code that uses ImageIO classes to get all
of the images comprising a given animated GIF and then view them as an
animation. I already have all the code to do this via NON-ImageIO classes
but I'm not clear on what I need to do if I use ImageIO classes instead.

In my existing animated GIF viewer, I simply execute this code and the
entire GIF with all of its images is read and loaded into a MediaTracker;
all I need to give it is the URL that points to the animated GIF:

animatedGif = Toolkit.getDefaultToolkit().getImage(animatedGifUrl);
MediaTracker mediaTracker = new MediaTracker(this);
mediaTracker.addImage(animatedGif, 0);
try {
mediaTracker.waitForAll();
} catch (InterruptedException i_excp) {
//error handling
}

My paint() method simply does the following:

g.drawImage(animatedGif, 0, 0, this);


What happens if I want to use the ImageIO classes? Do I need read and load
each image in the GIF separately? Or can I suck the entire GIF with all of
its frames into the MediaTracker in a single gulp like in my old code?

Does anyone have a code fragment that illustrates what I need to do? I could
figure this out by trial and error but I thought I'd try to "work smarter,
not harder" for a change :)

Also, for bonus points, can anyone tell me exactly why it is better to do
this via ImageIO classes than the way I did it before? In other words, what
are the benefits of ImageIO classes over older approaches? Both approaches
involve standard Java classes so I'm guessing ImageIO classes have better
performance?
 
T

Thomas Fritsch

Rhino said:
I've started working with the ImageIO but there is something I don't see
in
the API Guide or the API.

Basically, I would like to write code that uses ImageIO classes to get all
of the images comprising a given animated GIF and then view them as an
animation. I already have all the code to do this via NON-ImageIO classes
but I'm not clear on what I need to do if I use ImageIO classes instead.
I think this is where class javax.imageio.ImageReader comes in.
ImageReader has a getNumImages() method. I would guess that for GIF images
it returns the number of frames in the GIF file.
And ImageReader has a lot of methods getXxxx(int imageIndex, ...) which
probably allow you to access the individual frames.

But I never tried it myself, so may be I am wrong.
 
R

Rhino

Thomas Fritsch said:
I think this is where class javax.imageio.ImageReader comes in.
ImageReader has a getNumImages() method. I would guess that for GIF images
it returns the number of frames in the GIF file.
And ImageReader has a lot of methods getXxxx(int imageIndex, ...) which
probably allow you to access the individual frames.

But I never tried it myself, so may be I am wrong.

Nor have I, which is why I asked the question. It is very convenient to just
give the whole animated GIF with all of its images to the MediaTracker and
have it handle everything for me; I'd like to do the same with ImageIO if I
can. But if I have to parse the animated GIF file and load each frame
individually, that's fine too. I'm just hoping that someone has already done
this at some point and can tell me which approach I need to take.

I already have code to determine the number of images in the GIF but I don't
want to spend hours on trial and error if I can get the right answer from
the newsgroup.

Rhino
 
A

Andrew Thompson

Rhino wrote:

..It is very convenient to just
give the whole animated GIF with all of its images to the MediaTracker and
have it handle everything for me; I'd like to do the same with ImageIO if I
can.

From vague memory, animated GIF's loaded via ImageIO
do not cycle, you need to 'start a thread on them',
though I cannot recall more than that..

You might search on 'ImagIO Thread' examples at Sun...
 
R

Rhino

Andrew Thompson said:
Rhino wrote:



From vague memory, animated GIF's loaded via ImageIO
do not cycle, you need to 'start a thread on them',
though I cannot recall more than that..

You might search on 'ImagIO Thread' examples at Sun...

Thank you!

Following your suggestion, I found a useful, recent (but lengthy) article at
http://java.sun.com/developer/technicalArticles/Media/imagestrategies/index.html.
The following excerpt gives me a very big hint what the answer to the
question is (and also answers my bonus question about why ImageIO classes
are usually the best choice):

---
a.. Ease of Use: One of the goals of ImageIO was to expose more capabilities
to the developer. There is much information, such as metadata, in an image
that is not exposed through the old image loading methods or the old Image
class. The flipside of this approach (at least in the current API) is that
it can be more work to do trivial tasks. A good example of this is loading
and displaying an animated GIF.
In the old image loading APIs, if you loaded an animated GIF file, you did
not need to worry about the details of animating that image. Instead, you
could just load the image and display it and we would automatically schedule
the animations of that image appropriately. You could not access the
information about the animation (how many frames? what animation rate? loop?
halt?), but making it animate was quite simple.
ImageIO, on the other hand, exposes all of that animation information to you
through the API, but you must actually use that information to manage the
image animation yourself; you cannot just tell us to draw the image and have
us manage it for you. This is a known issue and we will do something about
it Real Soon Now.
---

In other words, the nice simple code I used to use to display my animated
GIF is not so simple with ImageIO; apparently, I have to parse the animated
GIF myself and send each frame to the MediaTracker one at a time. Or at
least that will be the case until they've dealt with this "known issue";
however, I'm assuming that the author is being ironic and "Real Soon Now" is
roughly equivalent to "when hell freezes over".

It's not the answer I wanted to hear but at least it's an answer and will
keep me from wasting a lot of time trying to make the simple way work.

Thanks again!

Rhino
 
T

Thomas Fritsch

Rhino said:
Nor have I, which is why I asked the question.
I know my answer was not a solution, only a kick into the direction I
would go.
It is very convenient to just
give the whole animated GIF with all of its images to the MediaTracker and
have it handle everything for me; I'd like to do the same with ImageIO if I
can.
You can. The example below processes an animated GIF and gets all its
individual frames, each as a BufferedImage. I checked it with
http://www.iconbazaar.com/images/animated.gif (has 44 frames).
But if I have to parse the animated GIF file and load each frame
individually, that's fine too. I'm just hoping that someone has already done
this at some point and can tell me which approach I need to take.

I already have code to determine the number of images in the GIF but I don't
want to spend hours on trial and error
not to say: spend time on reading the API doc ;-)
if I can get the right answer from the newsgroup.
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Iterator;
import javax.imageio.*;
import javax.imageio.stream.*;

public class Main {
public static void main(String[] args) throws IOException {
Object input = new File("animated.gif");
// or Object input = new FileInputStream("animated.gif");
ImageInputStream stream = ImageIO.createImageInputStream(input);
Iterator readers = ImageIO.getImageReaders(stream);
if (!readers.hasNext())
throw new RuntimeException("no image reader found");
ImageReader reader = (ImageReader) readers.next();
reader.setInput(stream); // don't omit this line!
int n = reader.getNumImages(true); // don't use false!
System.out.println("numImages = " + n);
for (int i = 0; i < n; i++) {
BufferedImage image = reader.read(i);
System.out.println("image[" + i + "] = " + image);
}
stream.close();
}
}
 
R

Roedy Green

not to say: spend time on reading the API doc ;-)

Unfair! Anyone with a name like Fritsch with a genetic inheritance
capable of parsing German sentences several pages long has an huge
advantage deciphering JavaDoc.
 
T

Thomas Fritsch

Unfair! Anyone with a name like Fritsch with a genetic inheritance
capable of parsing German sentences several pages long has an huge
advantage deciphering JavaDoc.
Thanks for the fish :)
Actually the problem of the JavaDoc is not (at least not in my opinion)
the length of sentences, but rather the many cross-links in it, so that
I get easily lost in following the links.
BTW: "Parsing" long german sentences is easier than parsing long english
sentences. For example: Your english sentence above translated to german
would have 3 or 4 commas, thus making its structure more obvious.
 
R

Roedy Green

Actually the problem of the JavaDoc is not (at least not in my opinion)
the length of sentences, but rather the many cross-links in it, so that
I get easily lost in following the links.
BTW: "Parsing" long german sentences is easier than parsing long english
sentences. For example: Your english sentence above translated to german
would have 3 or 4 commas, thus making its structure more obvious.

What I was referring to is that the skill required to parse long
German sentences requires one to be able to remember many facts that
are only later pulled together at the last second with the verb to
have meaning.

JavaDoc gives you many tiny pieces of information most of which are
irrelevant. You must however remember it all to put together a
framework of how all the classes and methods would be put together to
get something useful done.

It is a bit like being an archaeologist examining tools from an alien
culture try to guess what they were for and how they were actually
intended to be used.
 
T

Thomas Fritsch

Roedy said:
It is a bit like being an archaeologist examining tools from an alien
culture try to guess what they were for and how they were actually
intended to be used.
Did an archeologist ever find a tool together with a documentation how
to use it? ;-)
 
R

Roedy Green

Did an archeologist ever find a tool together with a documentation how
to use it? ;-)

The documentation typically tells you what it DOES not how to use it
or that it is for or how it is intended to used with other tools. You
can also get that "what it does" info from the source code. Tutorials
of various kinds are beginning to fill in that gap. You also need
what I might call master classes (in the music sense) aimed at the
more experienced user explaining in higher level terms what the
designers had in mind when they created the various classes as to what
sorts of problem they would be good for and which they would be
inappropriate for. They would also point out some of the quirkier
features you might overlook in the humdrum JavaDoc. You might more
irreverently call them the gotchas.

Similarly an archaeologist can measure all kinds of physical
properties about an artifact similar to information in Javadoc about
the logical properties of a method.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top