Which image format is more efficient to save memory? PNG, JPEG, or GIF?
|show 2 more comments|
"Memory" and "efficiency" are commonly misused terms, so I'll give you an answer for four different elements that may affect the performance of your game.
I will be oversimplifying way too many things to keep it short and concise, but there are tons of inaccuracies in this text below, so take it with a pinch of salt. However, the main concepts should be understandable.
This is the size your images consume on your software distribution. The more space your resources consume, the longer the download (as in from your website) will be. If you're distributing on physical media, such as CDs or DVDs, you're probably going to have to do some serious optimizations in this front.
In general, JPEG compresses the best for photographs and images with no sharp borders. However, your images will have degraded quality because JPEG uses lossy compression (you can fine tune the compression level/degradation when exporting images as JPEG. Refer to your imaging software's documentation for more information on this).
However, as good as JPEG may be, it doesn't support transparency. This is crucial if you want to have images that show through others, or if you want images with irregular shapes. GIF is a good choice, but it has been largely superseded by PNG (there's only a few things GIF supports that PNG doesn't, but they're largely irrelevant in game programming).
PNG supports transparency (and semitransparency), compresses data without degradation in quality (i.e. it uses lossless compression), and compresses fairly well, but not as much as JPG.
The problem arises when you need good compression, as well as transparency. If you don't mind slightly degraded images, you can use PNG quantization programs such as pngquant, which you can test online at TinyPNG. Keep in mind that the image degradation performed by quantization on its own is different than that of JPEG (which includes quantization as well as other aggressive techniques), so be sure to try both, with a wide variety of settings.
If you want to aggressively minimize your distribution size, you could manually process every image like this:
Tip: it is okay to store some images in one format, and others in another format.
There are other specialized formats such as DXT, ETC and PVRTC. They support compression, and can also be loaded compressed into memory, but they are only supported by specific GPUs, and most of these GPUs only support one of them, so unless you know the exact hardware specifications of your target hardware (a notable case is the iPhone/iPad, which supports PVRTC textures), you should avoid these formats.
I included it here, because this is what's commonly known by "memory". However, if your game uses graphics acceleration (and if you're making a game after 1998, you most likely are), then the only thing that will consume memory are your texture descriptors (just a few bytes per image), which is only effected by the amount of images, and not their size or format (this has a few caveats, but are mostly irrelevant).
If your platform does not have dedicated video memory, is not hardware accelerated, or other uncommon cases, then the next section regarding VRAM will happen completely or partially in RAM, but the main principles will be the same.
This is where your images will be stored once your program is running. In general, the format in which you stored them will make no difference here, as all images are decompressed before loading them into video memory.
Now, the VRAM consumed by your images will roughly be
Even though not "memory", it is very related with performance in games. Drawing images is expensive, and you want to make sure your rendering runs as fast as possible. Of course, in here, format doesn't matter, but other things do:
However, image usage optimization is a very complex topic, and what I wrote here is a very broad and oversimplified overview of some of the factors you will have to consider when writing a game, so I think it's definitely best if you keep it simple, and only optimize whenever you really need to do so. Most of the times, prematurely optimizing is unnecessary (and sometimes even detrimental), so take it easy.
|show 29 more comments|
Once an image is loaded off the disk and is formatted for rendering, it will use the same amount of memory regardless of whether that image was saved to disk using PNG, JPEG, or GIF.
General rule of thumb: JPEG is a lossy format, and will degrade image quality in order to make the image smaller on disk. PNG, on the other hand, is a lossless image format, and so will typically result in larger file sizes on disk. GIF is also technically a lossless format, but only supports a maximum of 256 colors per image, and so a high-color image will often incur a heavy quality loss if saved as a GIF.
That's only for their on-disk representation, though. In memory, they'll both expand into the same texture format, using the same amount of memory, regardless of whether you saved them to disk as PNG, or as JPEG, or as GIF.
Jpeg is most efficient for photographs. It isn't lossless, but the artifacts introduced by the compression are least visible in this use-case.
PNG is lossless and most efficient for pixel-art with sharp lines and few colors. It also supports alpha-transparency.
GIF can't do anything PNG can't do better, except for its ability to store animations. But this is only relevant in the context of web applications. In game development you usually create animations by using a spritesheet.
Note that when you use a graphic engine like Libgdx it will most likely uncompress the images just after loading them and then keep them in memory as uncompressed RGBA values. So the image format only matters for loading speed and had drive space (or bandwidth usage when you send them over the net).
I don't know much about libgdx, but about image formats and graphics:
JPEG is very good in cases of real world photos. They are lossy but you won't see artifacts on photos unless you take pictures of sharp edges with plain coloured spaces, like for example written text or comics. Use them for large background graphics.
GIF is obsolete, it can only store paletted colors (up to 8 bit per pixel) with one dedicated color for complete transparency. It allows small animations based on frames. Once there was a patent on its packing algorithm so that it could not be used everywhere legally. Because of that patent, PNG was developed.
PNG is more or less a zipped bitmap that can store RGB+alpha (up to 32bit) and other pixel formats. It is specialized for speed-unzipping of small parts of that picture, which is convenient for very small and slow devices (like a 10 year old cellphone), but todays libraries just unpack them to bitmaps when loaded.
PNG is better than GIF in size and speed and features, but if you want to store bitmaps efficiently, I'd suggest: .PNM.BZ2 (Because of the different packing method, .PNM.BZ2 is not always more efficient than .PNG.[/edit])
PNM/PBM/PGM/PAM are plain bitmap formats with K.I.S.S.-headers in plain text. Using gzip on those will result in a file size similar to PNG, so bzip2 is the better solution for that. If you are going to use bitmaps internally in your program, you might want to use bzip2 compressed bitmaps in a .tar or .zip container. If you don't have bzip2, using PNMs in a zip container (zip with maximum compression) might be similar to using PNGs. – So, storing PNGs in a ZIP file might have only small or no benefit – it would most likely just increase the time to load the image.
Besides that, it is a good choice to store several small sprites/pictures in one bitmap, especially when you need them all in the same situation together.
As storage format JPEG is probably the best choice for some textures like grass or walls, where the loss of information is probably undetectable. Followed by PNG when you need transparency or when you cannot pay with loss of information, for example sprites in a 2D game (the player, enemies, a treasury chest), you probably want to use PNG for that images.
When talking about memory cost, the format used to store game graphics in the file system is not relevant at all. Either if you store pixel buffers in VRAM, or RAM (software renderer), you probably have them stored uncompressed, because games favor fast read of pixels vs memory used by each pixel buffer.
Have compressed data stored in memory have no sense except you maintain some kind of cache to save disk reads, but you probably have to read from that cache to an uncompressed state for the images in use at a given time in your game.
Compressed image data have a bit more sense if fast hardware decoding were possible. For normal mapping at least, I remember this http://en.wikipedia.org/wiki/3Dc. With that you can save some VRAM. I'm not aware of other examples of hardware decoding yet.
In resume: whatever the formats used for your game to store graphics in persistent storage, you will have to decode that and maintain an uncompressed version in dynamic memory, video memory, or both, to be able to fast render them when needed.
Finally: I'm a desktop guy. When I say "memory" I always referring to dynamic memory. When I say "disk", "file system" or "persistent storage" I always referring to whatever your device use as persistent storage, usually I think in hard disks. When you said "memory-efficiency" I took it for "dynamic memory" not "persistent storage". Lately, I see a lot of people using the word "memory" to refer to "persistent storage" (maybe that the terminology of mobile devices?).
protected by Byte56♦ Apr 19 at 16:17
This question is protected to prevent "thanks!", "me too!", or spam answers by new users. To answer it, you must have earned at least 10 reputation on this site.