PNG - Not What You Need

I was dead happy with PNG format for a while. It was open, efficient, fully-featured, and available everywhere, and it turned out that it’s also available in Java.

The love affair is over!

Here’s why you don’t need PNGs for little games. Or even big ones:

  1. To load a PNG from Java typically you’ll be needing the AWT, and the ImageIO framework. This is a great big old bloater of an API designed to decode the kitchen sink if necessary. As usual, it is about 100x as complicated as you need to deploy your game. If, like me, you’re going to rely on native compilation that requires no JDK to be present, you’re pretty much stuffed because of the licensing agreement. This will mean you have to use another PNG library anyway - and that will almost certainly plug in to the AWT anyway.

  2. 90% of what is actually in the PNG file format has no relevance to you at all. PNG is a generic solution for storing graphics. You don’t hava a generic problem. You’ve got a very specific problem: you’re writing a game and that game has to be delivered on the Internet in demo form. My views on Internet delivery are unorthodox because they are not the views of a tech-savvy nerb but instead the views of a businessman who understands internet delivery. So all you nerds with cable modems / infinite patience out there - can it, I don’t want to hear it. If your demo is over 5Mb very few people with bother to download it and you can take this as gospel for the foreseeable future.

So now that’s all clear, what do I suggest you do about it? Well, at the risk of plugging the SPGL, I suggest you use your own image format.

Here are the advantages of using your own format. Or more specifically, my Image format:

  1. It relies on… 1 class! That’s right; the whole Image thing is only one class, and the amount of code in that class is tiny. It deals with loading and saving images and getting direct access to the image data - and that’s all it does. So not only is it tiny it’s also much faster than using AWT. Data is loaded directly into a Buffer - so it can go straight to OpenGL.

  2. The compression is vastly superior to PNG format. I was actually quite gobsmacked. Because we know that game sprites have certain properties which are different from generic images we can do a few special optimisations to the image compression. In my case, I split the image into its planes, so that each R, G, B, and A plane comes after the next instead of all packed as RGBA integers. Then for each line of the image I am recording just the delta of one colour to the next. This leads to an awful lot of very small integers, like 1, 0, and -1, in longer runs, which compress very well using gzip.

So as I mentioned in the diary: 4Mb of graphics suddenly has become 2Mb of graphics. This is good because A.F. was already considerably over 5Mb, and therefore on the road to commercial failure.

Cas :slight_smile:

I have to say I dislike file formats that include compression systems, at least for lossless compression anyway. I like my images to be good at being images, and leave the problem of making them smaller to the archive they’re stored in or the protocol they are transferred across. Why bother compressing an image internally these days; it only really affects the amount of disk space it uses - who’s running out of that?

As for containing too much info, PNGs can be stripped down to just three chunks - IHDR, IDAT and IEND. That should make them a bit smaller. But you still have to implement your own LZ77 inflate/deflate algorithm. After removing it from an already compressed archive…

I currently use SGI and TGA image formats for everything. SGI’s header contains a bit more than required, but most of it boils down to zeros. It stores pixel data in the same form/order to OpenGL. TGA stores pixel data in seperate channels, which compresses nicely with large blocks of colour. Both formats provide optional (i.e. totally ignored) RLE encoding, and both formats (can) treat the image origin as bottom left. Nice!

It’s all about downloads. There’s no magic you can do to the Wise self-installing .exe to get your images cleverly compressed… I mean, I really wouldn’t bother if this were going on a CD, but it’s primarily going to be digitally delivered. As are most people’s demos. That’s where it counts. It’s as important to make a good demo as a great game.

Cas :slight_smile:

I’m with this, as long as the images are easy to convert and they are capable of having 32 bit colors.

There’s absolutely nothing funny going on in the code - it’s just a tiny header explaining the type, dimensions, and length etc. and then gzipped delta planar data. It’s in sourceforge right now so have a look.

Cas :slight_smile:

I wrote a PNG 1.0 encoder/decoder once before that was included in Sun’s Java implementation. It does not support all the chunks, but it does support the standard ones and all image types I think. The encoder and decoder are written as two separate classes so there are not a bunch of small classes to keep track of, but both classes depend on the java.zip package for compression/decompression. The codec was written for an image editing application project so it used raw arrays rather than the standard java image classes.

Is there any interest from any of you people with library projects going to include such a codec in your libraries? I can probably clean up the classes and send them to you, but I will only do it if they would actually be useful to anyone since I soon expect to get busy with my own project (see volunteer projects section).

Cas, the more you write about it - the more it souds like you’re using the wrong tool for the job and should be importing the JVM into C as opposed to using C libs from Java.

Sometimes I think it’s that way round as well. But to be honest I’d write the whole thing in straight C or C++ if I wanted to make life easy for myself :slight_smile: My enemy is still the size of core Java. I really, really, want a J2ME VM specifically tailored for games, for Win32 and Linux. If they could just get it down to under a meg and as fast as the server VM I’d be sold but it won’t happen any time soon.

The advantages in using Java are probably only going to become apparent in the next game I write. Most of my code is reusable or very easily refactored. The same can’t usually be said of the final horrible stages of dragging a C++ game into production unless you’ve got rather more time on your hands.

I’ve got to remember that I only started A.F. in December so it’s had less than 3 months of part-time work on it. It would have been less probably if I’d hacked it all up in C++ but then I suspect that trying to use the code for the next game - probably Quest For The Holy Grail - would be counterproductive.

Cas :slight_smile:

Cas, your decoder is faster than the png one ?

Well, it uses the same zlib decompressor that comes with Java so I suspect it’s about the same. The crucial difference for us LWJGL devs is that it does it all in bytebuffers so we can directly shove it into OpenGL. And of course, the fact that it stores sprites at around 50% of the size of compressed .PNGs. And even more of course, it doesn’t rely on 1,000 other classes to be loaded prior to using it.

Cas :slight_smile:

I think its rather moot to compare a format you created to PNG. PNG format is not that bad of a format and has lots of uses. But even the groups who make PNG recognize that its not always the best tool for the job.

http://www.libpng.org/pub/png/pngintro.html

Does your format cover 256 layers of partial transparency? Probably not if its intended for games. But whoever said PNG was good for games? I myself prefer GIF and BMP for that. Thats more of an issue of preference and ease of use since both those formats can be edited with tools like Photoshop or GIMP.

PNGs a good format. Maybe not for games … but it has its uses.

Er, yes, exactly.

Cas :slight_smile:

Here is a nice library, not too large that does PNGs, its also used by the gl4java guys.

http://www.sixlegs.com/software/png/

The jar itself is only 60k in size and comes with a load of source code as well.

Regards,

Andy.

It’ll still require images 100% bigger than they need to be though. And sixlegs drags in a huge chunk of the AWT as well…

Cas :slight_smile:

Why not just announce you created a program that reads in your own image format rather than compare it to PNG? Discrediting PNG wont make your code any more appealing to game developers since there are plenty of other formats in the world to choose from. Information that might make it appealing:

  1. What bit formats does it support (4, 8, 16, 32, etc)?
  2. Transparency?
  3. Animation?
  4. Color palette?
  5. Render speed?
  6. Size of compression?

Arguments over “number of classes” or “size in megabytes” is redundant. If a developer is concerned about these issues he/she could just as simply opt not to use your format and just use Java’s core support for GIF and/or JPEG since your format adds both a class and increases the apps footprint. Food for thought.

Precisely. If you read the post again, I’m not discrediting PNG, which I think is an excellent general image format. However, its use in Java brings a ton of extra code you don’t need, and the image footprint on disk/download is twice as high as can be achieved when compressing game sprites.

I was shying away from outright demanding that people use my code :slight_smile: Besides, it’s open source so you can see if it fits your criteria, but anyway:

1 & 2 & 4. Supports 8-bpp colour channels: Alpha, Luminance, Luminance Alpha, RGB, RGBA, BGR, BGRA, ARGB, ABGR. Oh, and 8-bit palette.
3. No animation. It’s an image file format, not an animation file format.
5. It’s not a rendering component, it’s a data store. It’s for use with LWJGL, which does the rendering.
6. Compression is considerably better than .PNG files (approx 50% original size for my sprites, YMMV).

I think you’ve misread the whole post somewhere ;D Those are exactly the issues I’m raising. My format adds one class and removes about 1,000 other classes. But I can’t stress this enough: most importantly it achieves far better compression than .PNG for game sprites.

Cas :slight_smile:

What are you using to get your images to your image format in the first place? I’m playing with SPGL right now and I need some acual image data to load. :stuck_out_tongue:

Tomorrow (edit: later today since it’s 3am) I’m gonna write a java .png->puppy image converter unless you got one I can look at? :slight_smile:

Edit: btw I like the new puppy logo, no offense, but the old one made me want to stab myself blind. :slight_smile:

;D

The SPGL tools, in the same CVS as the rest of SPGL. There’s a sprite-packing thingy in there, and a resource converter, and an image converter. The sprite-packing thingy works well with the sprite engine in SPGL.

Cas :slight_smile:

Edit: sonofabitch. What you were saying just clicked, I just looked at the sourceforge page and indeed there is spgl-tools, which I don’t have. It just wouldn’t do for me if I didn’t look like a jackass EVERY day. :stuck_out_tongue:

Thanks Cas. :slight_smile:

2nd edit: I just looked at the tools, yay. Mabey I’ll get something going today.

Hmm, by using the PNG loading with AWT, will it slow down my game, even if I´m loading the images when I start the game? And what will the license stop me from doing exactly? And why is PNGs bad for games, don´t really get it? :wink: