Link Search Menu Expand Document

How to use Image Transcoder

Tired of having to do these conversions myself, I quickly decided to code a dedicated tool to do the job for me: Image Transcoder. The arrival of a new team at the helm of the Gamebuino ship made me want to upgrade my tool and give it a coat of varnish.

First of all, I suggest you to download the assets, i.e. the graphic resources of the project, which we will convert into C++ code. This will save you from having to redraw everything, unless you want to discover Piskel or another graphic tool of your choice…

Spritesheet Tileset Palette

Once downloaded, store them in a folder named artwork, at the root of your project:

Project folder

The new content of your project folder

You will notice that the palette defined in the palette-1x16.png file has exactly 16 pixels, although the last one is completely transparent. This was not mandatory, the transcoder can handle an incomplete palette. In general, I encourage you to make the most of the 16 colors allowed with the indexed color display modes.

Final palette

palette-1x16.png

Transparent pixels in an incomplete color palette (with less than 16 colors) will be assigned the color code with index 0x0 by default. If this color is itself transparent then it will be assigned the 0x0000 code of black.

Demonstration

Using the transcoder is very simple. I guess a video demo will be enough. For example, let’s convert our tileset for use with an indexed color display mode:

Image Transcoder

Demonstration of the Image Transcoder tool

It’s quick and easy. In a flash, the conversions are done!  

In the case of indexed color display modes, if you do not provide a palette file, the Gamebuino palette will be applied by default:

Gamebuino Palette

Gamebuino official palette

Therefore, if the image to be converted does not contain any of these colors, all pixels in the image will be assigned the default index color 0x0 (i.e. black).

It’s your turn!

Now it’s your turn. Convert the project assets for RGB565 and indexed color display modes, setting the transcoder correctly:

Use Image Transcoder to convert your images into C++ code

Organization of the project

We will split the asset codes into two separate files:

  • rgb565.h for RGB565 display mode
  • indexed.h for indexed color display modes

I suggest you download them:

rgb565.h indexed.h

We will then place these files in a directory named assets to structure our project and not to put everything in bulk at the root. The disadvantage with the Arduino IDE is that by isolating the asset files in a specific folder instead of putting them in the root of the project, it is as if the editor does not see them. You’ll see that you can’t open the assets folder. To get around this silly quirk, just create an empty assets.ino file in the assets folder:

Project folder

The new content of your project folder

This way, you can make it look like you’re opening another sketch next to the main sketch:

Main sketch Auxiliary sketch

This is an easy way to access the rgb565.h or indexed.h files from the Arduino IDE code editor when you need to make changes to them.

But the main my-stunning-game sketch is the one from which you should always start compiling and uploading to your Gamebuino. It is the starting point for the whole compilation process. The idea is to include the right asset file depending on the display mode you have chosen and defined in the config-gamebuino.h file.

DISPLAY_MODE_RGB565

my-stunning-game.ino

#include <Gamebuino-Meta.h>
#include "assets/rgb565.h"

void setup() {
    gb.begin();
}

void loop() {
    gb.waitForUpdate();
}

DISPLAY_MODE_INDEX or DISPLAY_MODE_INDEX_HALFRES

my-stunning-game.ino

#include <Gamebuino-Meta.h>
#include "assets/indexed.h"

void setup() {
    gb.begin();
}

void loop() {
    gb.waitForUpdate();
}

Converted and ready-to-use assets for C++

Now let’s see the details of these two asset files. The SPRITE_DATA and TILESET_DATA arrays characterizing the spritesheet and the tileset are gathered here. To avoid multiple inclusions, you should also remember to add the #pragma once precompilation directive at the beginning of each of these two files:

assets/rgb565.h

#pragma once

const uint16_t SPRITE_DATA[] = {

    // metadata

    8,      // frame width
    8,      // frame height
    4,      // frames
    4,      // frame loop
    0xf81f, // transparent color
    0,      // 16-bits color mode

    // colormap

    // frame 1/4
    0xf81f, 0xf81f, 0x632c, 0xad55, 0xad55, 0xad55, 0xf81f, 0xf81f,
    0xf81f, 0xf81f, 0xee2f, 0xff36, 0xff36, 0xff36, 0xf81f, 0xf81f,
    0xf81f, 0xf81f, 0xee2f, 0x0000, 0xff36, 0x0000, 0xf81f, 0xf81f,
    0xf81f, 0xf81f, 0xee2f, 0xff36, 0xff36, 0xff36, 0xf81f, 0xf81f,
    0xf81f, 0xf81f, 0x7afa, 0xb4df, 0xb4df, 0xb4df, 0xf81f, 0xf81f,
    0xf81f, 0xf81f, 0xff36, 0xb4df, 0xb4df, 0xb4df, 0xff36, 0xf81f,
    0xf81f, 0xf81f, 0x7afa, 0xb4df, 0xb4df, 0xb4df, 0xf81f, 0xf81f,
    0xf81f, 0xf81f, 0x6217, 0xf81f, 0xf81f, 0x6217, 0xf81f, 0xf81f,

    // frame 2/4
    0xf81f, 0xf81f, 0x632c, 0xad55, 0xad55, 0xad55, 0xf81f, 0xf81f,
    0xf81f, 0xf81f, 0xee2f, 0xff36, 0xff36, 0xff36, 0xf81f, 0xf81f,
    0xf81f, 0xf81f, 0xee2f, 0x0000, 0xff36, 0x0000, 0xf81f, 0xf81f,
    0xf81f, 0xf81f, 0xee2f, 0xff36, 0xff36, 0xff36, 0xf81f, 0xf81f,
    0xf81f, 0xf81f, 0x7afa, 0xb4df, 0xb4df, 0xb4df, 0xf81f, 0xf81f,
    0xf81f, 0xff36, 0x7afa, 0xb4df, 0xb4df, 0xb4df, 0x7afa, 0xff36,
    0xf81f, 0xf81f, 0x7afa, 0xb4df, 0xb4df, 0xb4df, 0xf81f, 0xf81f,
    0xf81f, 0xf81f, 0xf81f, 0x7afa, 0x6217, 0xf81f, 0xf81f, 0xf81f,

    // frame 3/4
    0xf81f, 0xf81f, 0x632c, 0xad55, 0xad55, 0xad55, 0xf81f, 0xf81f,
    0xf81f, 0xf81f, 0xee2f, 0xff36, 0xff36, 0xff36, 0xf81f, 0xf81f,
    0xf81f, 0xf81f, 0xee2f, 0x0000, 0xff36, 0x0000, 0xf81f, 0xf81f,
    0xf81f, 0xf81f, 0xee2f, 0xff36, 0xff36, 0xff36, 0xf81f, 0xf81f,
    0xf81f, 0xf81f, 0x7afa, 0xb4df, 0xb4df, 0xb4df, 0xf81f, 0xf81f,
    0xf81f, 0xf81f, 0xff36, 0xb4df, 0xb4df, 0xb4df, 0xff36, 0xf81f,
    0xf81f, 0xf81f, 0x7afa, 0xb4df, 0xb4df, 0xb4df, 0xf81f, 0xf81f,
    0xf81f, 0xf81f, 0x6217, 0xf81f, 0xf81f, 0x6217, 0xf81f, 0xf81f,

    // frame 4/4
    0xf81f, 0xf81f, 0x632c, 0xad55, 0xad55, 0xad55, 0xf81f, 0xf81f,
    0xf81f, 0xf81f, 0xee2f, 0xff36, 0xff36, 0xff36, 0xf81f, 0xf81f,
    0xf81f, 0xf81f, 0xee2f, 0x0000, 0xff36, 0x0000, 0xf81f, 0xf81f,
    0xf81f, 0xf81f, 0xee2f, 0xff36, 0xff36, 0xff36, 0xf81f, 0xf81f,
    0xf81f, 0xf81f, 0x7afa, 0xb4df, 0xb4df, 0xb4df, 0xf81f, 0xf81f,
    0xf81f, 0xf81f, 0x7afa, 0x7afa, 0xff36, 0xb4df, 0xf81f, 0xf81f,
    0xf81f, 0xf81f, 0x7afa, 0xb4df, 0xb4df, 0xb4df, 0xf81f, 0xf81f,
    0xf81f, 0x6217, 0xf81f, 0xf81f, 0xf81f, 0xf81f, 0x7afa, 0xf81f

};

const uint16_t TILESET_DATA[] = {

    // metadata

    16,     // frame width
    8,      // frame height
    4,      // frames
    0,      // frame loop
    0xf81f, // transparent color
    0,      // 16-bits color mode

    // colormap

    // frame 1/4
    0x1926, 0x1926, 0x1926, 0x1926, 0x1926, 0x1926, 0x1926, 0x1926, 0x1926, 0x1926, 0x1926, 0x1926, 0x1926, 0x1926, 0x1926, 0x0000,
    0x1926, 0x1926, 0x10e4, 0x1926, 0x10e4, 0x1926, 0x10e4, 0x1926, 0x10e4, 0x1926, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x0862,
    0x1926, 0x10e4, 0x1926, 0x10e4, 0x1926, 0x10e4, 0x1926, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x0862,
    0x1926, 0x1926, 0x10e4, 0x1926, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x0862,
    0x1926, 0x10e4, 0x1926, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x0862,
    0x1926, 0x1926, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x0862,
    0x1926, 0x10e4, 0x1926, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x0862, 0x0862,
    0x1926, 0x1926, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x0862,

    // frame 2/4
    0x4228, 0x632c, 0x632c, 0x632c, 0x632c, 0x632c, 0x632c, 0x632c, 0x632c, 0x632c, 0x632c, 0x632c, 0x632c, 0x632c, 0x632c, 0x632c,
    0xad55, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228,
    0x632c, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228,
    0x0000, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186,
    0x18c3, 0x0000, 0x18c3, 0x0000, 0x18c3, 0x0000, 0x18c3, 0x0000, 0x18c3, 0x0000, 0x18c3, 0x0000, 0x18c3, 0x0000, 0x18c3, 0x0000,
    0x0000, 0x18c3, 0x0000, 0x3186, 0x0000, 0x18c3, 0x0000, 0x3186, 0x0000, 0x18c3, 0x0000, 0x3186, 0x0000, 0x18c3, 0x0000, 0x3186,
    0x3186, 0x0000, 0x3186, 0x0000, 0x3186, 0x0000, 0x3186, 0x0000, 0x3186, 0x0000, 0x3186, 0x0000, 0x3186, 0x0000, 0x3186, 0x0000,
    0x0000, 0x18c3, 0x0000, 0x18c3, 0x0000, 0x18c3, 0x0000, 0x18c3, 0x0000, 0x18c3, 0x0000, 0x18c3, 0x0000, 0x18c3, 0x0000, 0x18c3,

    // frame 3/4
    0x1926, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x0862, 0x0862,
    0x1926, 0x1926, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x0862, 0x10e4, 0x0862,
    0x1926, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x0862, 0x0862,
    0x1926, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x0862, 0x10e4, 0x0862,
    0x1926, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x0862, 0x10e4, 0x0862, 0x0862,
    0x1926, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x0862, 0x10e4, 0x0862, 0x10e4, 0x0862, 0x10e4, 0x0862,
    0x1926, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x10e4, 0x0862, 0x10e4, 0x0862, 0x10e4, 0x0862, 0x10e4, 0x0862, 0x10e4, 0x0862, 0x0862,
    0x0000, 0x0862, 0x0862, 0x0862, 0x0862, 0x0862, 0x0862, 0x0862, 0x0862, 0x0862, 0x0862, 0x0862, 0x0862, 0x0862, 0x0862, 0x0000,

    // frame 4/4
    0x0000, 0x632c, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x18c3,
    0x632c, 0x3186, 0x18c3, 0x3186, 0x18c3, 0x3186, 0x18c3, 0x3186, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x0000,
    0x3186, 0x18c3, 0x3186, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x0000,
    0x3186, 0x3186, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x0000,
    0x3186, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x0000, 0x0000,
    0x3186, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x0000, 0x18c3, 0x0000, 0x18c3, 0x0000,
    0x3186, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x0000, 0x18c3, 0x0000, 0x18c3, 0x0000, 0x18c3, 0x0000, 0x18c3, 0x0000, 0x0000,
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x18c3

};

In the case of the assets file for the indexed color display modes, the definition of the color palette, which is common to SPRITE_DATA and TILESET_DATA, has also been added. The header file <Gamebuino-Meta.h> must also be included since it contains the declaration of the Color class that is used for the palette definition :

assets/indexed.h

#pragma once

#include <Gamebuino-Meta.h>

const Color PALETTE[] = {

    (Color) 0x0000, // 0x0
    (Color) 0x18c3, // 0x1
    (Color) 0x3186, // 0x2
    (Color) 0x4228, // 0x3
    (Color) 0x632c, // 0x4
    (Color) 0xad55, // 0x5
    (Color) 0xee2f, // 0x6
    (Color) 0xff36, // 0x7
    (Color) 0x0862, // 0x8
    (Color) 0x10e4, // 0x9
    (Color) 0x1926, // 0xa
    (Color) 0x6217, // 0xb
    (Color) 0x7afa, // 0xc
    (Color) 0xb4df, // 0xd
    (Color) 0xf81f, // 0xe
    (Color) 0x0000  // 0xf

};

const uint8_t SPRITE_DATA[] = {

    // metadata

    8,    // frame width
    8,    // frame height
    0x04, // frames (lower byte)
    0x00, // frames (upper byte)
    4,    // frame loop
    0xe,  // transparent color
    1,    // indexed color mode

    // colormap

    // frame 1/4
    0xee, 0x45, 0x55, 0xee,
    0xee, 0x67, 0x77, 0xee,
    0xee, 0x60, 0x70, 0xee,
    0xee, 0x67, 0x77, 0xee,
    0xee, 0xcd, 0xdd, 0xee,
    0xee, 0x7d, 0xdd, 0x7e,
    0xee, 0xcd, 0xdd, 0xee,
    0xee, 0xbe, 0xeb, 0xee,

    // frame 2/4
    0xee, 0x45, 0x55, 0xee,
    0xee, 0x67, 0x77, 0xee,
    0xee, 0x60, 0x70, 0xee,
    0xee, 0x67, 0x77, 0xee,
    0xee, 0xcd, 0xdd, 0xee,
    0xe7, 0xcd, 0xdd, 0xc7,
    0xee, 0xcd, 0xdd, 0xee,
    0xee, 0xec, 0xbe, 0xee,

    // frame 3/4
    0xee, 0x45, 0x55, 0xee,
    0xee, 0x67, 0x77, 0xee,
    0xee, 0x60, 0x70, 0xee,
    0xee, 0x67, 0x77, 0xee,
    0xee, 0xcd, 0xdd, 0xee,
    0xee, 0x7d, 0xdd, 0x7e,
    0xee, 0xcd, 0xdd, 0xee,
    0xee, 0xbe, 0xeb, 0xee,

    // frame 4/4
    0xee, 0x45, 0x55, 0xee,
    0xee, 0x67, 0x77, 0xee,
    0xee, 0x60, 0x70, 0xee,
    0xee, 0x67, 0x77, 0xee,
    0xee, 0xcd, 0xdd, 0xee,
    0xee, 0xcc, 0x7d, 0xee,
    0xee, 0xcd, 0xdd, 0xee,
    0xeb, 0xee, 0xee, 0xce

};

const uint8_t TILESET_DATA[] = {

    // metadata

    16,   // frame width
    8,    // frame height
    0x04, // frames (lower byte)
    0x00, // frames (upper byte)
    0,    // frame loop
    0xe,  // transparent color
    1,    // indexed color mode

    // colormap

    // frame 1/4
    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0,
    0xaa, 0x9a, 0x9a, 0x9a, 0x9a, 0x99, 0x99, 0x98,
    0xa9, 0xa9, 0xa9, 0xa9, 0x99, 0x99, 0x99, 0x98,
    0xaa, 0x9a, 0x99, 0x99, 0x99, 0x99, 0x99, 0x98,
    0xa9, 0xa9, 0x99, 0x99, 0x99, 0x99, 0x99, 0x98,
    0xaa, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x98,
    0xa9, 0xa9, 0x99, 0x99, 0x99, 0x99, 0x99, 0x88,
    0xaa, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x98,

    // frame 2/4
    0x34, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
    0x53, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
    0x43, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
    0x02, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
    0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
    0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,

    // frame 3/4
    0xa9, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x88,
    0xaa, 0x99, 0x99, 0x99, 0x99, 0x99, 0x98, 0x98,
    0xa9, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x88,
    0xa9, 0x99, 0x99, 0x99, 0x99, 0x99, 0x98, 0x98,
    0xa9, 0x99, 0x99, 0x99, 0x99, 0x99, 0x89, 0x88,
    0xa9, 0x99, 0x99, 0x99, 0x98, 0x98, 0x98, 0x98,
    0xa9, 0x99, 0x99, 0x89, 0x89, 0x89, 0x89, 0x88,
    0x08, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x80,

    // frame 4/4
    0x04, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x21,
    0x42, 0x12, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10,
    0x21, 0x21, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10,
    0x22, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10,
    0x21, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00,
    0x21, 0x11, 0x11, 0x11, 0x11, 0x10, 0x10, 0x10,
    0x21, 0x11, 0x11, 0x01, 0x01, 0x01, 0x01, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01

};

Now everything is ready to display our beautiful assets on the screen. There was a lot of things to say and do before we started programming. But I hope that everything is now clearer in your mind about how to prepare your assets before bringing them to life with code. See you in the next chapter for the rest.