Best way to load images.

Hello all. If I want to store and load images for a game, what is the best way to go about it? I’m interested in the following:

Hardware-acceleration? (If I remember correctly, this rules out Toolkit.getImage()).

Format? I hear PNG is the best. I’m interested in basic, small sprites (32x32 or 64x64) with single transparency (BITMASK?)

Transparency? Last time I tested, for some reason, TRANSLUCENT was actually better and faster than BITMASK. This was around the release of 1.4.0.

Classpath? Using ImageIO and Toolkit, they want a URL or a filename. If you JAR up your entire package including images, it makes more sense to use getResourceAsStream(). I’d rather my images be found on the classpath than through absolute or relative file names.

So in essence, I’m looking for the best format to write an image in for gaming. Afterwards, I’d like to load that image and maintain transparency, have hardware-acceleration, and be found on the classpath.

Too much to ask? I’m hoping there’s some kind of best practice. No third-party libraries either. I’m aware of GAGE and LWJGL, but this is a learning exercise for me and I’d like to do it using core libraries and extensions. Some of you might remember my Pacman project over a year ago, and I’m trying to improve on that again. The images were rendered at runtime using Arc2D and Rectangles, so I never worried about loading them before.

Thanks for any help!

Michael Bishop

Ooooh so many questions… where to start?

Loading of images:

The best way to do that is using ImageIO. Right now you need to copy it to a freshly created BufferedImage (createCompatibleImage) wich is setup with the desired transparency mode in order to get a nice accelerated (managed) image.

I recommend to checkout Balls.jar by Abuse. It’s a little test programm (source included). It should be easy to find by using the search funktion of this board.

Btw the BufferedImages of ImageIO will be managed by default in 1.5 :slight_smile:

Format:

Sure PNG is a good choice… it’s often the best one, but not always. I recommend to use a tool like PNGCrunch or pngout (by Ken Silverman) to shrink the PNG files to a minimum (pngout is better but takes 10-100 times longer). Btw the PNGs from Photoshop tend to be quite huge (even free image-viewers such as IrfanView are better for that task).

Also if you have alot of images, wich are identical in their dimension it’s quite easy to put em all into one file. This way you can save the overhead from the fileheader plus more efficient encoding (more data=more ways to crunch it). Well that’s only true as long as you can keep the palette (however that’s usually not a big deal if it’s about animations for one character ;)).

You can either use the CropImageFilter or do that on your own while you are copying the images (in order to get em managed).

It’s straightforward:


BufferedImage[] tiles = new BufferedImage[10];
for(int i=0;i<10;i++)
{
      tiles[i] = gc.createCompatibleImage(12,12,Transparency.BITMASK);
      tg = (Graphics2D)tiles[i].getGraphics();
      tg.setComposite(AlphaComposite.Src);
      tg.drawImage(tilesImg,
            0,0,
            12,12,
            i*12,0,
            i*12+12,12,
            null);
      tg.dispose();
}

In the case above I have 10 tiles in one PNG file (120x12 pixels).

Obviously it makes sense to encapsulate that functionality into your custom image loader… Image-URL and cut width are given… and it returns an array of managed images (or something along that lines).

Transparency:

Opaque is faster than Bitmask (as long as the image doesnt have alot of transparency and the overdraw isn’t that huge).

Bitmask is faster than Translucent (that should be always that way - can’t think of a scenario were it would be otherwise nore I’ve seen such a case).

Classpath:

Well… I can’t really answer this one… since I hadn’t tried that. However, packing the images into a seperate jar makes only sense if you want to use webstart. Just adding that jar to the classpath and using relative URLs should be fine :slight_smile:

Btw don’t use compression in for the jar in that case (just “store”) in order to load 'em a bit faster. The files aren’t good compressable anyways since they are already packed damn well :wink:

this could help also http://wiki.java.net/bin/view/Games/LoadingSpritesWithImageIO

Yes, so many questions, but so many good answers. Oddly enough, my current ImageManager class gave the user the ability to create a compatible Image and load an Image from a File. I was on the right track. Thanks a lot for the concise and solid answers to my many questions. That pretty much nailed it for me.

Michael Bishop