PNGB is a command line utility that converts PNG files to GBDK data definitions and code.
I’ll host binary builds of this program soon. In the meantime you can download the source and Window binary build from the GitHub Repo.
What is this good for?
PNGB can take a PNG image, slice it in 8×8 (or 8×16 if you are using GB “big sprites”) tiles and output a single C source code file containing the pixel data, the color palette, attribute array and a tilemap (that recreates the source image using the extracted tiles).
It can additionally generate “test code” that allows you to see (to some extent) the result of the conversion and how to use the data.
PNGB currently supports 8×8 tiles (BKG or WIN layers) and Sprites (both 8×8 and 8×16).
It also supports color pictures. If your image has 4 colors or less PNGB will generate an equivalent 15-bit palette for GBC. For images with more than 4 colors you’ll have the options to let PNGB convert it to grayscale first and then attempt to match each color with one of the four shades of the original Gameboy.
Currently PNGB can only generate a single palette for the whole image, but in a future it may be able to extract multiple palettes from a single image.
Examples
So let’s see some examples. For instance take this lovely 4-frames sprite:
It’s using 4 colors and each frame is 8×16. We want the palette data so we can convert it with PNGB using
pngb -B -p -c sprite.png test.c
(-B is for big sprites and -p is to output the palette. If you already have your palettes in your code you don’t need that). I’m also generating test code (that’s what the -c flag is for) so I can show you what’s going on.
Well, that’s not really… uh.. good, right?
What happened here is that for Sprites -both in the original GB and GBC- the first color of the palette is always transparent.
And I’m guessing that black is the first color of this one, so let’s fix that.
We run PNGB again with -tr #ffffff, which basically tells PNGB that white (RGB #FFFFFF) is the transparent color and should be moved to the top of the palette. This is the result:
If you use an emulator like VirtualBoy you can debug the sprites, tiles and palette data easily and it may help you when this kind of problem is not particularly obvious.
Now let’s move to a tiled background. We will attempt to convert this:
Please notice that it’s a 160×144 image, which means it’s 20 tiles wide and 18 tiles tall, which in turn means it has 360 tiles, more than the allowed 256 tiles that can be defined in the GB tile memory block. I’m trying this so you can see how/why it fails and how we can use some features of PNGB to get away with this. Running
pngb -K -p -c stage.png state.c
gives a C code output that compiles to the following:
Ok, we knew from the start that it wasn’t going to work because the image is too big and has too many tiles. If we check the output we will see that in fact PNGB generated 360 tiles. However, in the case of this picture is obvious that the number of unique tiles is very low and we shouldn’t be trying to convert such an obviously bloated picture in the first place!.
We can tell PNGB to perform tile reduction (-e option), which should detect and remove duplicate tiles, leaving us with a tight set of unique tiles and a tilemap that contains updated references to the reduced Tileset. Let’s see if that works:
Voilá. According to the output, PNGB generated only 11 tiles, and in fact we can see how tiles were reduced/reutilized in the output code:
You can also see that currently the attribute map is mostly useless because we are using a single palette for the whole set. If you change the palette number from the command line however, you’ll see that the map will be updated accordingly and in a future if we support multiple palettes this will actually be useful data.
Since it’s already working in color it won’t hurt to see how our stage looks in the classic Gameboy, so we force the emulator to behave as a non-color old-school GB:
Well, that’s…. not exactly how I think it should look… :/ The problem here is, that the palette of our picture looks like this:
The Original Gameboy has a fixed palette that goes from “white” to “black”, with 2 shades of gray in the middle and it will use that fixed palette to render our tiles, ignoring our palette, so our dark red/brown will look white, our dark gray will look light gray, our yellow will be replaced with dark gray and our light gray with black.
To fix this we can instruct PNGB to sort the palette (-s), this will re-arrange our colors from light-est to dark-est. If we do that, this is what we get:
And now it runs well on the GBC and the GBC, thanks to a properly sorted palette (ironically enough, our palette was exactly in the reverse order of what would have made sense for the Gameboy).
Anyway, this example ended up demonstrating some features of PNGB that can actually ease the development of graphics for the GB. You can even use the tile-map features as a quick way of building simple levels if you are in a hurry! (not recommended though. Building your stages in an image editing program is far from ideal).
There are other options like customizing the palette index that will be used, or the base sprite ID, or converting the full image to grayscale, etc. I hope to add more in a future but hopefully the current feature set will already be enough to help at least someone out there with their project!