How to create and load transparent images
to use them within browser-based Java gaming:
a tutorial with free source code for download.
Transparent images are essential for game objects, e.g. robots, rockets, explosions. The graphics for such objects are typically created in a rendering or paint software. They must then be exported in a file format supporting transparency, ideally PNG. If the rendering software cannot export PNG directly, but some other format supporting alpha channels, then this can still be turned into PNG through many freeware converters.
But how do we load this within browser Java?
- load the PNG directly? Two problems here: PNG's are 10 times larger than JPEG, so it would take far too long to load them from the internet. Second, many (older) browsers do not support PNG loading at all - so we may have to use 3rd-party PNG reader classes. Although there are some really good reader classes available, we always end up with a far too long downloading time.
- one thing's for sure, it must have to do something with JPEG. Concerning download (and game startup) time, every single byte matters, and only JPEG provides the maximum compression. So we have to convert the original PNG to JPEG. But JPEG provides no transparency!
- so how do we "make a JPEG transparent"?
First, I tried greenboxing - use all green pixels within a JPEG as a transparent background. Unfortunately, due to the compression, you can never expect that an original "full green" (0x00FF00) really keeps it's color code. The result: the objects frayed, and showed ugly borders.
So there's no way around - we have to store the transparency information separately from the JPEG. But in what format?
- GIF? Just google for "GIF patent", and ask no further. Although some of the patents may have elapsed by now, no one will ever again feel comfortable with it.
- PNG again? Yes, I tried also to put a single-bitplane image (black/white) into a PNG, but then again, I had the problem that I needed special support classes just for loading this, to be all-browser compatible. And after all, the goal is just to load a simple byte array into memory.
- an own file format? First I thought this would be lots of effort, as we need compression. But then I remembered the standard Java package java.util.zip!
So, within the image converter d3conv, I extract the alpha transparency from the original PNG, and have it as a byte array within memory. I then simply have to dump this array into a compressed file, using Java's Zip classes, and to reload this within the engine. Therefore you find a .zip file for every .jpg requiring additional transparency.
I even took this one step further: because we now have many small .zip files, we can speed up loading again by packing them all together in one large wrapper .zip file, called masks.jar (a .jar is technically identical to a .zip). We don't even have to write code to do so - a simple command "jar cfM masks.jar *.zip" does the job!
Some further notes about d3conv:
This tool actually implements two methods of transparency in parallel: the alpha channel mask, and whiteboxing. So, if you have any "pure white" areas in your original image, that is, colors of code 0xFFFFFF (red=255, green=255, blue=255), they will also be considered as transparent. The reason is that we need some way to display object shadows - to have a shadow, the object must be standing on some kind of ground, otherwise the shadow will not be visible. But in the game, we don't want this original ground, as the object will stand on something else. So the ground must be identified and removed - and therefore it's white.
Be aware that if you have white areas on your actual objects, you have to reduce the color a bit into grey, e.g. to red=254, green=254, blue=254, otherwise your object will end up with transparent holes.