
My point here is that it’s kinda unfair to compare game content to a single image on the internet.įrom the game side, you start with a small set of re-usable tiles, and index them to build up your larger image, we can do this, because we know how the game is going to be made. The below image is a 5.9kb PNG file, while the JPG image is 106kb Since this image has lots of duplicate pixels (the blue sky background) compressors like PNG do a better job than their block-based JPG counterparts. This is why an image with a very uniform background will always be smaller as a PNG instead of a JPG. The result is that long runs of similar pixels can end up being cut down to a much smaller size.

PNG compression is entirely lossless, (so your image quality is high, but your compression savings are low), and based on the DEFLATE codec, which pairs LZSS along with Arithmetic Compression. This doesn’t happen that often.ĭespite its other flaws, PNG is much better in this regard. So, the only place where two blocks might get compacted into 1 block, is if their post-DCTd version is identical, and RLE can make stride recommendations. A block-view of how JPG image compression works.

It’s only after this step, does a lossless encoder come along, and see if it can match up common duplicate groups using DPCM, or RLE. This generally means there’s a lower-bound on how a given block of data is compressed.įor example, JPG breaks a given image into 8x8 pixel blocks, converts the RGB color space into the YCbCr version, and then applies Discrete cosine transform on them. The result is that for a given 16x16 pixel block, these algorithms assume it’s unique among the image Besides some color quantization, there’s no real logic added to determine if another 16x16 block could be an exact duplicate of the current one. JPG, PNG, WebP have all been designed for photos and not so much game screens. Generic image compression algorithms have no domain knowledge about the pixels inside of them. Here’s the “ not fair” part of this comparison. Now let’s talk about generic image compression. Even 3D games will have a set of common textures that are applied multiple times and places throughout the game itself. So with concepts like tile-sheets and sprite-sheets, we can use a small set of images to create large scenes & worlds. Behold, that level that you parents could never complete.

(I talk about this in a lot more detail in Lesson 3 of my HTML5 Game Development course Udacity, or in my book HTML5 Game Development Insights.) Tack on some Run-Length-Encoding, or some basic LZ77, and you get a fairly compact format for levels. The levels themselves, just became a giant 2D array of indexes into the sprite sheet. For example, below is a remake of the original super mario sprite sheet: It’s not the exact original sprite sheet, but you can get a sense of the small blocks of data that can be use over-and-over again.Įach small 16x16 pixel square represents a “tile” and artists would string these together to create the actual levels. Sprite sheets contain small tiles of graphics, that are re-used over and over again. Basically, a subset of the 1MB cartridge data must be loaded into the 2kb RAM and used to render the 180kb screen. So, there was no way to fit the entire game’s contents into main memory. A cartridge itself could could hold 8k to 1mb of game data.

The original NES console was only designed to output images that were 256 wide by 240 high meaning that the final image that needed to be displayed to the screen was 180kb in size.īesides that, the NES only had 2kb of RAM. So let’s talk about how the original Super Mario game worked, from an asset perspective. I want to set something clear here though : we’re not really comparing Apples-to-Apples, so let’s define some technologies first. Great question Dion! I will answer it, and not just because you’re my new boss, but because it’s a good question. By Colt McAnlis Where do all the bytes come from?
