PNG to CPP

This page will guide you through the logic of converting a PNG file to a C++ file. You won't see any code here because the idea is that you can take what you learn and then apply it to any language you want. I used Python and I'll provide my version at the end of the page if you want to download it. I highly recommend writing your own version though in whatever language you want. You can also probably find tools that others have written that will do this conversion for you. But like I said, I'm a big fan of trying to work out the logic and write my own little converter before looking around what others have done.


PNG Image Example


Overview

Take a look at the images above. I'm going to use these images as the example when explaining the concepts here. On the left you have a PNG image of a familiar looking mushroom. Now, if you were to open that PNG file you'd find that the image is actually composed of 3 channels. The red, green, and blue channels. The image on the right shows what each of these channels looks like by themselves. Combining the three channels together into a single image produces the image on the left. This is because in the image on the left each pixel has an (r,g,b) component. Each rgb value ranges between 0 and 255. The value of 0 means completely black and the value of 255 results in the full color. So if all three channels have a value of 255 for a pixel, or (255, 255, 255), then the color of that pixel would be white. If the color values are (255, 0, 0), then the color of that pixel is red. That's why if you see red in the image on the left, you'll see the same red in the red channel, but black in the green and blue channels.

The Game Boy Advance has less colors to work with. While most computers nowadays can have color values ranging between 0-255 resulting in millions of colors. Each color channel uses up a byte since a byte can be 256 different values: 28 = 256. Multiply that by 3 channels: 224 = 16,777,216 colors. The colors on the Game Boy Advance only range from 0-31 since it uses 15 bits to define the colors: 215 = 32,768. So one of the things we have to do is convert a 24-bit color to a 15-bit color which is pretty straightforward.


Color Palette


Paint By Numbers

If you take a look at the tables on the right you'll see a smaller one-row table on top and a larger table below that. The larger table is essentially a representation of the mushroom image here. This mushroom is 16x16 pixels and so is the table. The small one-row table above it is the color palette for the larger table. This palette contains all of the colors that make up the image. This is a fairly simple image and only contains 5 unique colors. You can easily see that the numbers in the larger table correspond to a color in the color palette. If I took my paint brush and colored each pixel with it's corresponding color, I would just end up with this image exactly.

0 1 2 3 4 5 6 7 8 9 A B C D E F
0
0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0
0 0 0 1 1 4 4 4 4 2 2 1 1 0 0 0
0 0 1 2 2 3 3 3 3 2 2 2 2 1 0 0
0 1 2 2 4 3 3 3 3 3 2 2 2 2 1 0
0 1 2 4 3 2 2 2 2 3 3 2 2 2 1 0
1 4 3 3 2 2 2 2 2 2 3 3 3 3 4 1
1 4 3 3 2 2 2 2 2 2 3 3 2 2 4 1
1 2 3 3 2 2 2 2 2 2 3 2 2 2 2 1
1 2 2 3 3 2 2 2 2 3 3 2 2 2 2 1
1 2 2 4 4 4 4 4 4 4 4 4 2 2 4 1
1 2 4 4 1 1 1 1 1 1 1 1 4 4 4 1
0 1 1 1 5 5 1 5 5 1 5 5 1 1 1 0
0 0 1 5 5 5 1 5 5 1 5 5 5 1 0 0
0 0 1 5 5 5 5 5 5 5 5 5 5 1 0 0
0 0 0 1 5 5 5 5 5 5 5 5 1 0 0 0
0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0

VBLANK and VSYNC

The basic size of a sprite is 8x8 pixels, and we call that a "Tile". That means this sprite has 4 Tiles since it is 16x16 pixels. So we need to divide it into its 4 Tiles as shown below. The top left portion of the sprite is the first tile, then we move right to get the next tiles. Then we move down to the left to get the third tile and the remaining portion is the last tile. You basically start at the top left and scan from left to right, then move down a row and scan from left to right again.

The result is the four tiles shown below. Now, how do we store this in code?

00000111
00011444
00122333
01224333
01243222
14332222
14332222
12332222
11100000
42211000
32222100
33222210
23322210
22333341
22333341
22322221
12233222
12244444
12441111
01115515
00155515
00155555
00015555
00000111
23322221
44442241
11114441
51551110
51555100
55555100
55551000
11110000

Reverse Values and Store in Array

We can now store these values into an array of hex values where each row is a 32 bit hex value. For each tile there are 8 values in a row and each value is 4 bits (if we are using 4bpp mode). But before we can store in an array we need to reverse the values. The reason you do this is how the GBA stores values. You may have heard of little edian or big edian. The GBA uses little edian to store values, that means it will store the least significant byte first. Each value you see below is 4 bytes since each digit is 4 bits. More on this later...

So, for example, if we have the value 0x12345678 that needs to be reversed to 0x87654321. Below are the final results of the four tiles above where each row in the tile is grouped into a single hex value, and each hex value is reversed before storing in an array.

Tile 1 = {0x11100000, 0x44411000, 0x33322100, 0x33342210, 0x22234210, 0x22223341, 0x22223341, 0x22223321}

Tile 2 = {0x00000111, 0x00011224, 0x00122223, 0x01222233, 0x01222332, 0x14333322, 0x14223322, 0x12222322}

Tile 3 = {0x22233221, 0x44444221, 0x11114421, 0x51551110, 0x51555100, 0x55555100, 0x55551000, 0x11100000}

Tile 4 = {0x12222332, 0x14224444, 0x14441111, 0x01115515, 0x00155515, 0x00155555, 0x00015555, 0x00001111}


Place arrays in code

Once you have that you can place these arrays into your code wherever you need them. But how we actually implement them is covered in other sections on this site. Good places to check out are the OAM and any of the tutorials in the Mode 0 section.

That's basically the gist of taking an image and converting it into something the GBA can read. It's up to you to write a program that can actually do the conversion. I'm sure there are some out there, and in any case I'll provide my own program that you can use.