For sure not a lot of people is using “save as .h” capability in TheGimp. But this is a really easy to use solution when you want to embed some icons or image into a C/C++ source code. I used this functionality with Arduino to display graphical elements and I was convinced of it.

I also reused this format to transfer an image over Bluetooth as this format have the advantage to encode RGB values into printable characters. The format is not too much expensive as 3x8bits RGB values are encoded with 4 chars.

This post gives detail on this encoding and a procedure example to encode your bitmap into this format. The decoding procedure is given by TheGimp in the .h file itself.

Each of the RGB values are encoded with 4 chars and each of the values are split into different char. The objective is to convert 3 values in a 0 – 255 range into 4 values into a 33 – 96 as these values of characters are all printable ( from ‘!’ to ‘`’ ).

The given function to decode the converted data is the following one (translated in java)

for (int y = 0; y <tab.length; ++y) { for (int x = 0; x < tab[y].length; ++x) { int[] data = new int[4]; data[0] = (int) textImage.charAt(index); data[1] = (int) textImage.charAt(index + 1); data[2] = (int) textImage.charAt(index + 2); data[3] = (int) textImage.charAt(index + 3); index += 4; tab[y][x] = new Rgb(); tab[y][x].r = (((data[0] - 33) << 2) | ((data[1] - 33) >> 4)); tab[y][x].g = ((((data[1] - 33) & 0xF) << 4) | ((data[2] - 33) >> 2)); tab[y][x].b = ((((data[2] - 33) & 0x3) << 6) | ((data[3] - 33))); } }

The last 3 lines are extracting the R,G,B values form the 4 characters of each pixel. You can notice that each time you manipulate a character you have “-33” this is to move values from printable character space (33-…) to the decimal space (0-…). Then as an example, you can notice R is based on 6 bits coming from data[0] and 4 bits from data[1]. This sounds like 10 bits but as the 2 highest bit from each byte have to be clear to ensure we are in the printable space, they will be 0. Rq : (6 bits = 0-63) => [33 – 96] in the printable space.

The next function is the opposite operation to get the 4 char encoding from the 3 RGB values :

byte[] data =newbyte[4]; data[0] = (byte) ((r >> 2) + 33); data[1] = (byte) ((((r & 3) << 4) | ((g & 0xF0) >> 4)) + 33); data[2] = (byte) ((((g & 0x0F) << 2) | ((b & 0x60) >> 6)) + 33; data[3] = (byte) ((b & 0x3F) + 33);

Here we clearly see that 6 highest bit of R are stored in data[0] ; data[1] stores the 2 last bit of data[1] and force the two highest bit value to 0 (mask & 3 on r). the lower quartet of data[1] is storing the 4 highest bits of G value …

If you convert the Data table in the value space you have the following values:

data[0]-33 = [ 0|0|R7|R6|R5|R4|R3|R2 ] data[1]-33 = [ 0|0|R1|R0|G7|G6|G5|G4 ] data[2]-33 = [ 0|0|G3|G2|G1|G0|B7|B6 ] data[3]-33 = [ 0|0|B5|B4|B3|B2|B1|B0 ]

Hope this will remove some mystery !