Image loading....

I was reading the Java2D (iPlanet painting) article from the Swing Connectio and noticed them using this to load an image that they paint as a panel background:

BufferedImage image = ImageIO.read(“background.jpg”);
imageFill = new ImageFill(image);

Now from what I’ve read here on JG, BufferedImages are the (only?) kind of image that cannot be accelerated. So wouldn’t it have been better for them to do a Toolkit.getImage? Why, in this performance-minded article, would they use a BufferedImage? I think the name’s misleading, as it “sounds” faster than a Image :slight_smile:

Thanks!

P.S.> The reason I ask is because it seems nice and tempting to use the ImageIO class to load images, (read methods) but all it can return is BufferedImages, and I don’t want to forgo the (automatic) images that are accelerated (when available).

If you’ve got other reasons for using ImageIO please ignore this, but there’s much more sensible ways of loading images for games in Java if you’re interested in performance.

Use your own file format for a start if you can. Plain gzip with a header is absolutely adequate where once you might have used .PNG or .GIF. If you need to use JPEG then you’re probably better off using ImageIO, but otherwise you cut down on a vast amount of overhead and crud that gets dragged along with the ImageIO libraries and Java2D.

Secondly, as you are using your own file format, you can load them directly into whatever storage you want - for example, straight into a VolatileImage. If you’re lucky the VolatileImage will be in exactly the same byte-format as your image data; otherwise you’ll have to translate the pixels on the fly into the native format from your image format.

Thirdly, if you’re doing cleverer stuff with native libraries then load the image data directly into a ByteBuffer. If you’re sending the image directly to DirectX or OpenGL or SDL then this is by far and away the fastest way of doing things, and uses a fraction of the memory.

Cas :slight_smile:

Thanks for the info princec, I hadn’t even considered using my own file format, you have good points.

ImageIO is good because the formats it can load is extensible. Also, it provides a lot more control over how the image is loaded (including what ColorModel to use).

A handy thing about loading into a BufferedImage is that you can do some pre-rendering-processing on it. And if you want speed, after you finish the processing you can convert it to an automatic Image using a MemoryImageProducer, or by creating an ImageProducer that reads directly from the BufferedImage.

I’d debate the values of using your own image format. First, that requires a converstion step in the art pipeline. Second, any new features you’ll have to add yourself. Say you need a transparency channel down the road; now not only do you have to change your format, but you have to modify the converter AND the loader. I recommed you find an exsiting format and work from that: PNG is a good one, as it’s fairly simple, yet has a lot of options (plus ImageIO supports it).

If load time is an issue, wait until near the end of the project to convert all the images to the most efficient format. Worrying about that during dev will only cause you grief.

I’m mostly concerned with little things like icons at this point, so the custom format, as you pointed out, is a bad idea (as photoshop will just laugh at me).

FYI: it’s only the current state of affairs that BufferedImage’s aren’t accelerated. In future releases we’re planning to have all of the images acceleratable.

As pointed out, ImageIO allows for much greater extensibility. For example, you can combine the benefits of having your own file format with the standard infrastructure already in place by writing your own ImageIO plugin (ImageReader/Writer). You can make it read the files into whatever images you like, then.

princec,

I am assuming that in order to use a custom format, you’re responsible for also writing some form of converter, right?

Yep.
I convert from .PNG files using ImageIO.
Source code is in http://sourceforge.net/projects/spgl - look around the CVS in the “tools” section, there’s an image converter in there, and in com.shavenpuppy.jglib.Image you’ll find the actual image class I use myself. It’s a WIP at the moment as I’m adding palette support.

Cas :slight_smile:

If we are talking about performance, maybe following will do: Have original images in any format you want (jpg,png,anything). Then, when running for the first time on given system, check screen resolution/format you want to use. Then convert all images to this format, in raw form on disk. If for some reasons, format of screen has changed, you will need to purge the cache and convert again.

If you feel brave, you can even construct one big file, to avoid file open/close calls, and use one big MappedByteBuffer to access it.

Performance…

So how about the quickest way of loading them to a window/frame from disk. Something like:


Frame f = new Frame(); // created somewhere else just as a reference
 
Image theImage;
MediaTracker mt = new MediaTracker(f);
mt.addImage((theImage = Toolkit.getDefaultToolkit().getImage("whatever.png)),0);
try {
   mt.waitForID(0); // to make sure the image is loaded
}catch(Exception e) {}
// and then draw to the frame with a render or via paint/repaint

With an Image 512x512x32bit (68793bytes in PNG) on a Sun SunBlade 100 256Mb ram it the procedure will have an average of 300milliseconds I tested with a WinXP 1.4GHz 256Mb ram and it had an average of 200milliseconds. There must be a quicker way!

gZi 8)

Thanx for your reply, rsk. Modified the code. Loading the frame should be done alot earlier. But from your answer I assume there are no faster way?

I can only assume the frame creation is slowing you down, that’s expensive :frowning:

I don’t typically like this solution, but using an ImageIcon will do exactly the code you just posted, minus the frame creation because it keeps a static reference to a Component that it uses.

So you can use the ImageIcon class to speed things up (since it Component is already creataed for you).

Hey!

now i have a problem concerning image loading.

I have menu that when i click a button removes old content of container and draws new one. The point is, that after clicking i have to wait short time to let the image load completely. It’s only when i do it first time. Then i can click “back” and it will show fast.

I’m trying to prepare preloader of those backgrounds, and all graphic (jpg) files for menu.

Can someone please give me some hints, becouse as for now - it’s my second day fighting with this problem, and i obviously need help.

Thx in advance.

i use my own image format gzip over my special image format.

I wrote my own converter in C++, but its easy for a professional to do this in 2 or 3 hours.

For my tilesets its the best solution, i can compress better than gif or png, because i know all special properties, which gif or png does not know.

for isometric tiles some pixels will be never used, but gif or png compresses them, believe me you will have less trouble if u use your own image format.