Image Loading Speed

I’m using the following code to load images to display.


ImageIcon ii = new ImageIcon(imageLocation);
                  Image loadedImage = ii.getImage();
                  
                  int imageWidth = loadedImage.getWidth(null);
                  int imageHeight = loadedImage.getHeight(null);
                  
                  if (getGraphicsConfiguration() != null)
                  {
                        Image acceleratedImage = getGraphicsConfiguration().createCompatibleImage(
                                    imageWidth, imageHeight, Transparency.TRANSLUCENT);
                        acceleratedImage.getGraphics().drawImage(loadedImage, 0, 0, null);
                        loadedImage = acceleratedImage;                              
                  }

The funny thing is this, I’m loading a 1360x768 image to display as a background and after doing several time trials I found something weird.

As a GIF - ~9s
As a PNG - ~18s
As a JPG - ~19s

Astonshing! And after I went through my images and made them all GIFs, my program loads 10s faster then before. Any ideas why GIFs are loading that much faster? And am I the only one who’s had this happen?

The file sizes are different. GIFs are usually the smallest. JPEGs can vary based on the compression setting.

Nice try but try again. The JPG at maximum quality is 150kb while the GIF is 500k.

No thanks

Thanks for your help anyhow. :slight_smile:
Hope I didn’t offend you but I was going for gameshow humor.

don’t realy have any idea with regard to the load speed, but I can spot 1 problem :smiley:


Image acceleratedImage = getGraphicsConfiguration().createCompatibleImage( 
      imageWidth, imageHeight, Transparency.TRANSLUCENT); 

unless you are using the setProperties() to enabled the experimental accelerated alphacompositing, that code will not result in an image elligable for acceleration :stuck_out_tongue:

also, when copying the loaded image onto the accelerated image, you should set the Compositing rule to ensure the alpha channel of the Src image is preserved. (ofcourse, it will make no difference in that example… but others it will)

Ah!
I didnt get the humor part and was making a “bad post” but thought better of it. Glad I did :wink:

Interesting. The strange thing is that I have other transparent images and they work fine with transparency as it is. Dunno how I got that for free.

However after tracing the code I found that the moving the images to the BufferedImage doesn’t actually affect speed at all. It takes roughly 0ms (according to System.currentMillisecs()) and once drawn are quite fast. (Maybe cuz I have a Athlon 1800+, dunno).

The real culprit is

new ImageIcon(fileName)

It takes about 120ms to load a 140byte GIF. Since I have about 40 GIFs at that size, it quickly adds up to a big delay. And the 1360x768 GIF takes about 7~9s depending on the JVMs mood.

[quote]Interesting. The strange thing is that I have other transparent images and they work fine with transparency as it is. Dunno how I got that for free.
[/quote]
ah, thats prolly cos images created that way have all their pixels initially set to transparent anyway.
(though I don’t know if that is a guaranteed behaviour or whether it may change between platforms/jre versions)

have you compared the speed of that with… ?


ImageIO.read(getClass().getResource(filename));

Ah, I gotcha. Yeah since I created those images I can definitely say they have transparent pixels.

BTW, I think I’ve finally narrowed it down. I tried on a whim to load a completely different image first. Turns out no matter what image I load, I get an initial 7s delay from ImageIcon. This surprised me when a 100 byte GIF took 7s to load. And after testing I get this no matter which image I use. Now, granted that I get about 1s extra from the 1360x768 image. But that’s acceptable. The 6~7s pause it what’s unacceptable.

Oops forgot to mention that I think MediaTracker is somehow behind this, although I’m sure you all figured that out anyhow :slight_smile:

[quote]Ah, I gotcha. Yeah since I created those images I can definitely say they have transparent pixels.

BTW, I think I’ve finally narrowed it down. I tried on a whim to load a completely different image first. Turns out no matter what image I load, I get an initial 7s delay from ImageIcon. This surprised me when a 100 byte GIF took 7s to load. And after testing I get this no matter which image I use. Now, granted that I get about 1s extra from the 1360x768 image. But that’s acceptable. The 6~7s pause it what’s unacceptable.
[/quote]
that’ll teach u to be lazy and use ImageIcon :smiley:

have you any idea of the overhead of using that method :S

new ImageIcon(file);

then creates a MediaTracker.

but, because the media tracker needs a component,

it also creates a Component to pass into the mediatrackers constructor.

creating a Component will cause the entire AWT system to fire up (including the event scheduler etc etc etc)

hence the 6second delay ::slight_smile:

solution… don’t use ImageIcon() :smiley:

Abuse, you are…well……my hero…the wind beneath my wings…

But seriously Thank you very very much. That was definitely it. Using ImageIO took a 12s startup down to 2s. And that’ll definitely teach me to be lazy.

Thank you to everyone who helped.

glad to be a help, though i should mention ImageIO has a bug in it in java1.4.0, that prevents it from loading small images :S

also, some1 will prolly come in and say ImageIO is designed for dealing with image manipulation, and shouldn’t be used for loading images normally.

I disagree with that - and until some1 from Sun tells me otherwise i’m gonna stick 2 my guns… ImageIO all the way! :smiley:

but incase you do want to load the image the traditional way, this will do it…


public synchronized Image loadImage(String filename)
{
Image img = getToolkit().createImage(getClass().getResource(filename));

if(!toolkit.prepareImage(image,-1,-1,this))
{
   try
   {
       this.wait();
   }
   catch(InterruptedException e){}
}
return img;
}

public synchronized boolean imageUpdate(Image img, int flags, int x, int y, int w, int h)
{
   //there are a load of error conditions
   //that should be checked here,
   //i'm just checking for success
   if((flags & ImageObserver.ALLBITS) == ImageObserver.ALLBITS)
   {
       this.notifyAll();
       return false;
   }
   return true;
}

The bug is not there in 1.4.1_02 because I just tried loading a 1 pixel image and it worked fine. I discovered that no matter what I did, the initial delay was always around 1.2s for the first image. Turns out it doesn’t matter if it’s a 1360x768 or 16x16 image, ImageIO takes 1.2s to warm up. So, I had this idea, I’ll try to warm up ImageIO before I do anything else. Sure enough by loading a single pixel image (I’m sure size doesn’t matter though) before I do anything else (even starting my rendering loop) I cut down the initial delay to 100ms. Then it only takes 300ms for my background instead of 1.2s.

Hope this helps anyone else who might have this issue.

Another traditional way that you can load images, instead of doing this:

Image img = getToolkit().createImage(getClass().getResource(filename));

Is to do something very similar (which is the method I use), namely this:

Image img = Toolkit.getDefaultToolkit().getImage();