Bitmaps to RREFont to LCD Display

Hey everyone!

So, I've got an ILI9341 2.8" TFT display, and it works great. I'm using cbm80amiga's ILI9341_Fast library.

My application involves printing some large bitmaps, enough to cover the whole screen. Problem is, bitmaps take up a lot of progmem space. I know I can store bitmaps on the SD card and print from there, but I'd rather use cbm80amiga's RREfont bitmap solution because of the flexibility, speed, and scalability of the graphics. I already use the RREfont library for displaying text in an efficient way on the screen, and I was able to find the example in the video linked above. I need to be able to recreate that video with my own custom image, that's the goal.

I understand how this example is working- a bunch of custom RREfonts were generated from a base bitmap (rre_mario0.h, rre_mario1.h, rre_mario2.h, etc). One of these fonts is generated per color on the original bitmap image. Those fonts are loaded in, and printing characters like " " or "!" print the bitmap as if they were text (text that happens to be shaped like Mario). I'm really impressed with the speed, and at how efficiently this entire mario bitmap image is stored in Progmem. Very ingenious solution- I just don't know how to get my OWN bitmaps into RREfont formats.

When I open up one of the "fonts" (mario0.h for example), I see it mentioning "generated by RREfontgen". So I checked that out, here it is. Got it downloaded, and I figured out how to use cmd to navigate to that folder and execute commands listed in the github.

What I don't know is- how do I use this rrefont software to go from my own bitmap image into files equivalent to the rre_mario0 font files used in his examples? Honestly, I need a bit of a step-by-step guidance for this stage. If I can properly generate those RREFont files, I think I can print them just fine. How did he go from a bitmap of our beloved Italian plumber into the rre_marioX.h files? Everything after that I've got a good understanding of.

What I've tried: I took a bitmap (some random 32x32 sprite), made it monochrome for sake of being simple. Then, I took a wild guess and converted .bmp to .pbm (because .pbm is mentioned in the rrefontgen github). Tried running the command "rrefontgen image.pbm 32 32 testfont" (following instructions for using rrefontgen in pbm mode). This didn't work, error said I needed to specify "w and h in pbm file". I expected this, given that these were wild guesses. Thought I'd come ask a more experienced community what I need to be doing here.

I'm decently experienced using Arduinos, but not experienced with more in depth coding, like compiling .c files, using cmd to execute programs, and such. Took a while to learn how to convert a bitmap to a regular byte array for printing on the display the old fashion way. Got that done, but quickly realized that larger bitmaps would eat up my progmem.

Thanks for your help!

What size image do you want? e.g. 96x128 like the video
How many colours? e.g. 7 like the video
What target? e.g. Uno, ESP32, ...
Which display? e.g. ILI9341

How many different images?

The video is interesting in that one single picture can be scaled in X, Y directions.

You have to be realistic. There is no point in learning how to create the data files until you have thought about the practical limits for size and speed.

David.

david_prentice:
What size image do you want? e.g. 96x128 like the video
How many colours? e.g. 7 like the video
What target? e.g. Uno, ESP32, ...
Which display? e.g. ILI9341

How many different images?

The video is interesting in that one single picture can be scaled in X, Y directions.

You have to be realistic. There is no point in learning how to create the data files until you have thought about the practical limits for size and speed.

David.

  • Image size: Different images might be different sizes- some are likely to be in the neighborhood of 96x128, some might be full length 320xH- these bitmaps will represent different parts of the UI of a device I'm creating, so sizes will vary (buttons, menu bars, etc).
  • Sure, assume 7 colors. Again, these will be variable- but if I can learn how to accomplish this with something equivalent to the video I can myself determine what my other limitations should be, and the color splitting scales with the technique.
  • ATMEGA328P. Technically not an Uno- I'm putting the chip on my own PCBA. I know other chips have more progmem and can solve this problem in other ways- but that doesn't further my understanding of the workflow I'm asking about
  • As mentioned in my post- a 2.8" ILI9341 TFT Touch Display. Assume this one.
  • Not sure why the number of images is relevant- if I can learn how to do this conversion with 1, I can do this conversion with whatever number I need. Number of images IS relevant for the end program design, but the question I'm asking scales with number of images.
  • The X Y scaling is indeed very interesting- you'll notice that he achieves it by scaling the rectangles that form the basis of an RREfont (function customRectScale in his example). Overall just a very clever way of compressing font and bitmap information while maintaining usability, I gotta say.

While I appreciate the point you make regarding practicality, I'm not looking for help determining the overall design of what I'm building- I just need guidance on the specifics of the question.

The practicality and other concerns will be something I'll need to address as I evaluate the program after I can determine what types of benefits I achieve with this bitmap-to-rrefont workflow. (For example- I can of course use a combination of TFT shape primitives and bitmaps combined to achieve different UI elements on screen.)

I'll experiment myself with size and speed and other solutions (external EEPROMS, primitive shapes, different chips, all manner of creative solutions)- but I cannot do that without being able to test this RREFont system with my own bitmaps- hence the original question!

The reason for asking about size and number of different images is whether they might fit in a 32kB mega328P.
Run Length Encoding is pretty good for solid blocks of colour. Not much good for cross-hatching or intricate detail.

If you have too much data to fit in PROGMEM you are forced to use SD Card or external Flash chip.

Do you really want to scale images at runtime ?

If you go for an ARM or ESP chip not only do they have proper 3.3V GPIO but they have sufficient SRAM to decode full colour JPEG pictures or even full colour GIF animations.
And I suspect that both JPG and GIF will compress data better than RLE.

David.

Figured it out! Going to post my process here so others can see it. Basically, I split a bitmap into layers by color, converted to .pbm files, then used rrefontgen

  • Started with a bitmap with a few colors. Found a sprite from a website with basic game assets, just to get a sample picture. My sprite was a squid like character, with 3 colors, 80x80 px.

  • Opened it up in Paint.net, used the magic wand tool to separate every color in the bitmap to a different layer. Saved these as 1-bit bitmaps.

  • Saved each layer as a different bitmap. Did not make them monochrome- this will happen when we convert to .pbm files.

  • Opened Irfanview, went to file>batch convert

  • Batch converted all of these bitmaps into .pbm (with Binary encoding). Now we've got a handful of .pbm files. (mine are called squid1.pbm, squid2.pbm, and squid3.pbm)

  • Moved all of these pbms into the same folder as the rrefontgen.exe

  • Navigated to that folder with the command prompt. Ran this command: "rrefontgen squid1.pbm 80 80 squid1font"

  • That outputted a bunch of text to the command prompt. I coped everything below the dotted line at the end (to copy with cmd prompt, right click and select "mark", highlight the area you need to copy, and press Enter)

  • Pasted that data into text files renamed to squid1.h

  • For one of these .pbm files, I guess the rrefontgen found it to be too complex for 1 character- so I needed to split it into 4 characters. I used the command "rrefontgen squid3.pbm 40 40 squid3font"

  • Now we've got 3 .h files, these are our font files. If they only contain 1 character, then printing a " " (space) character will print the bitmap we converted. If there are multiple characters, you need to print the subsequent ones (look up an ASCII table to see what comes after " ")

  • This is what my code looks like to achieve the result:

#define TFT_CS A3 //10
#define TFT_RST 8 //9
#define TFT_DC 7  //8

#include <ILI9341_Fast.h>

ILI9341 lcd = ILI9341(TFT_DC, TFT_RST, TFT_CS);


/* --------------------------- Font initialization -------------------------- */

#define USE_RRE_FONTS 1
#include "RREFont.h"
#include "rre_term_10x16.h"
#include "squid1.h"
#include "squid2.h"
#include "squid3.h"
RREFont font;
void customRect(int x, int y, int w, int h, int c)
{
  return lcd.fillRect(x, y, w, h, c);
}

void setup()
{

  //Initialize LCD Screen
  lcd.begin();
  lcd.setRotation(3);

  //Set up RE Fonts
  font.init(customRect, SCR_WD, SCR_HT);

  //Initialize display setup
  lcd.fillScreen(BLACK);

 font.setFont(&rre_squid1font);
      font.setScale(1);
      font.setSpacing(0);
      font.setColor(WHITE);
      font.printStr(50, 50, " ");

      font.setFont(&rre_squid2font);
      font.setScale(1);
      font.setSpacing(0);
      font.setColor(CYAN);
      font.printStr(50, 50, " ");

      font.setFont(&rre_squid3font);
      font.setScale(1);
      font.setSpacing(0);
      font.setColor(BLUE);
      font.printStr(50, 50, " ");
      font.printStr(50 + 40, 50, "!");
      font.printStr(50, 50 + 40, "\"");
      font.printStr(50 + 40, 50 + 40, "#");

}

This successfully prints the bitmap!

EDIT: Incorrectly stated that it doesn't help program size- but it did! I saved 10742 bytes for this 80x80 3 color bitmap.

This topic was automatically closed after 120 days. New replies are no longer allowed.