using tft.pushColor to display PROGMEM rgb565 bitmaps

I would guess that you display digits in monochrome. And you probably display icons like petrol-pump or water-temperature in monochrome too.

It is considerably easier to have a Digits font and a Widgets font. You use setFont(), setTextColor(), setCursor() and print() just like you would with regular text fonts.

It is very simple to create a cut-down font from a regular font. e.g. just the 10 digits from a 224 character font.

I would also guess that your MG logo is in full-colour.

Yes, you can treat every letter, icon and logo as full-colour bitmaps on a microSD. Let's face it. SD cards give you unlimited storage.


well, the icons I've made are either single-color or two-color. Yes. But I have tried just making them monochrome and using Adafruit's drawBitmap function, and I wasn't happy with the results at all.

Here's what I've got so far:

They key is anti-aliasing. Even images and icons that were made deliberately using just one single color will look better anti-aliased, with smoothed edges. Anti-aliasing makes font characters and icons "blend in" with their surroundings, and edges in particular appear less rough and blocky than they would as a monochrome one-byte bitmap.

The twist is that anti-aliasing requires full-color pixel definition, or, in the case of black, at least grayscale.

Here's another look at a typical user interface submenu screen as I envision it:

When displayed values reach critical levels (e.g. less than 5 liters left in the fuel tank, or maybe an oil temperature above 120°C), the digits will appear in red. In addition to displaying a fullscreen warning message once for five seconds. So I will also need an array of "red" digits bitmaps.

Also, when one of the more safety-relevant warnings has been triggered (fuel, lights, oil temp, coolant temp, battery voltage), a corresponding icon will be displayed in the bottom row of the display, under the red horizontal line, and it will take turns every five seconds with the interior and exterior air temperatures that are normally displayed there.

I know that I am not making it easy on myself. But frankly, when comparing the results, there is no doubt in my mind that I want everything on my screen anti-aliased. Even if that will require practically writing my own miniature font library for the number digits.

Using actual monochrome would be easier to code and it would take less time too. But at the end of the day, the Adafruit display [u]is[/u] capable of what I've got in mind for it. And to me, even if it takes longer to achieve, that's what matters. I might have to teach myself a good number of things yet before getting there, but hey, to me, that's part of the fun. And my personal finishing deadline for this CarDuino isn't until next summer anyway, so I've got plenty of time to spend on these things still. ;)

Regarding two-colour icons. You can print the main colour in overwrite mode with the secondary colour in transparent mode.

I am not sure if I understand the anti-aliasing on a small display. Your petrol pump looks 27x27 and the big digits 18x27. I doubt if a pink pixel would blend better than a sharp contrast between white and red.

However, this is your project and designing the overall appearance is 100% important. We can possibly help with implementing your ideas.


david_prentice: I am not sure if I understand the anti-aliasing on a small display. Your petrol pump looks 27x27 and the big digits 18x27. I doubt if a pink pixel would blend better than a sharp contrast between white and red.

I know that to all of you, it probably seems like madness, or at least like a case of clinical OCD :D

I'm sorry if you've got that impression, and I mean no disrespect. But I can still see a difference between monochrome and full-color, even if it's on microscopic 25x25px bitmaps.

Have a look:

And I just uploaded it to the TFT screen. The differences are also visible on it, although, admittedly, only just.

david_prentice: However, this is your project and designing the overall appearance is 100% important. We can possibly help with implementing your ideas.

Like I said, I mean no disrespect in being dead set on doing it the way I envision. I just like to push technologies to their limits. That in itself is a big part of the fun for me.

I copied your image into IrfanView. It said it was 122x128 with 24 bits per pixel.

The difference in picture quality is certainly dramatic. Definitely worth doing. I do not understand how it is achieved.

I magnified the bitmap in IrfanView until I could see every individual pixel. I was expecting to see different coloured pixels for the "rounded edges". It just looked like a 1024x1024 high resolution image.

I am impressed. So much so, that I will copy the saved bitmap to a microSD and see it for myself on a 128x128 display.


david_prentice: I do not understand how it is achieved.

Fundamentally, anti-aliasing is a collection of different methods and algorithms to rasterize lines and circles and thus remove "jagging", which results from displaying "non-square" objects (which may contain circles or diagonal lines) on a pixel grid. You could say some of them are "averaging" algorithms, which take into account an object's shape around its edges as well as the color of the object's background.

Long story short, I'm glad you're with me now on the realization that it's worth going that extra mile with the graphics on my CarDuino ;)


Seeing as you have been creating your own font libraries, can I turn to you for questions that will probably pose themselves as I will write my own mini-font library (of sorts) for the anti-aliased display digits? I think I am really starting to understand the concept. The basics of it appear to not be that difficult once you've got your head around a few crucial things about arrays...

I will probably need to create three anti-aliased number digit font libraries. One will be "DS-Digital 38pt italic black", then one in "DS-Digital 38pt italic MG red" (RGB 143 10 10), and one more "DS-Digital italic Black", probably somewhere in the neighborhood of 25pt, which will be used to display inside and outside air temperatures. They will be fixed width, except for the dot, which I will probably want to have in half the normal width of the respective font.




Yes, you can ask questions but sometimes responses will be delayed by a few days as I have paid work to do as well :slight_smile:

No problem... I've got other things to do as well besides coding for a hobby project... ;)

As far as I can see now, my mini libraries are going to be fairly simple. In Arduino library terms anyway... :neutral_face: It's really just going to be about translating sensor readings into successions of equal-width number bitmaps, with eleven smallish bitmaps (including a "dot") per font, and three fonts in total.


Ok so I’ve started composing a library for my approach of displaying sensor readings as full-color anti-aliased bitmaps.

It would be great if you could have a quick glance at the files, just to tell me if I am on the right track at all with this…

This is my first-ever attempt at writing a library of my own, so please be lenient… :wink:

The centerpiece of this library will be the function valuesToBitmaps(), which is supposed to translate a float or integer that you feed into it into a succession of bitmaps.

I’ve attached the .h, .c and .cpp files…



I’ve come up with an idea to “rationalize” the displaying of the headers after all.

The left two-thirds of every header image are the same, it is only in the right hand side part that they differ. So an idea would be to divide the headers up into two files, one on the left, which always stays the same, and then the respective icon on the right for every submenu.

Like this:

Maybe then the headers could also be stored in PROGMEM. They would make up about 35 KB of the chip’s flash memory. On the other hand, the full-color bitmaps for the number digits will already take up a sizeable amount of memory…

DS38ptB.h (359 Bytes)

valueToBitmaps.cpp (1.61 KB)

DS38ptB.c (39.3 KB)


You will get multiple error messages if you try to use those files in a library as currently written.

Read this tutorial which will provide guidance. Post back when the files have been updated.

Note that you don't need to create a library, you can just add the files to a sketch, then you don't need a constructor, of course the route forward is your choice.

To be honest, I am not happy either with my first draft.

But I knew it wasn't going to compile; this was more about taking the first steps in the direction of writing my own Arduino library... not having done this before.

Anyway, I'll try to eliminate the bugs the next couple of days and make this library work.

While I’m still reading up on Arduino libraries, there’s another feature that’s maybe (?) a bit easier to implement.

I’m going to store the fullscreen warning icons as well as the welcome screen on the MicroSD card on the back of the display. I’ve read somewhere that theoretically, they should load faster if you store them right in RGB565 format as text files and don’t have to put them through a function like Adafruit’s own bmpDraw(), which converts RGB into 565 first before pushing the pixels to screen.

So how do I go about making a text file like that and reading from it?

I’ve attached the welcome screen as a .c file which I created using the “LCD Image Converter”, so you can see what I’m trying to start with… suppose I wanted to use the information contained in it to put that image on the TFT screen, what’s the best way to do that?

welcome.c (129 KB)

Yes, RAW 565 format is quicker to draw than a BMP format. There are several utilities that will convert a BMP to the 565 format. e.g. from the UTFT site.

Convert all your BMP files to 565 files and store them on your microSD.

If I have time this afternoon, I will look at your posted code. I am very impressed with the aliased images.

As a silly question. I have some 128x128 Red displays. They do not have SD sockets. However the 128x160 displays do have SD sockets. A microSD socket would be far more convenient than the big SD card holder.


I've got a "budget" generic 128x160 display from China, and it too only has an SD slot, not MicroSD.

I believe Adafruit only uses MicroSD/MicroSDHC these days on their displays. For this project anyway, I am using an Adafruit 128x128 with MicroSDHC.

david_prentice: Yes, RAW 565 format is quicker to draw than a BMP format. There are several utilities that will convert a BMP to the 565 format. e.g. from the UTFT site.

I've found the LCD Image Converter to be a good option:

It is also what I used to generate the "welcome.c" file that I posted above.

You don't store the C file on the SD. You create a raw binary file that contains the 128x128 pixels i.e. 32768 bytes.


Right… that was my guess also. Considering that BMP files in principle only contain pixel information as well, including a few header bytes…

Most BMP are 24-bit colour. i.e. 3 bytes per pixel + 54 odd bytes for the header = 48kB for 128x128 image
There are other schemes. e.g. 16-bit colour with 2 bytes per pixel + header
or 8-bit colour with 1 byte per pixel + palette table + header.

In practice, the palette table is a significant size for small BMPs. e.g. 512 bytes for 256 colours.

Your aliased icons could use 4-bit colour with a 16 colour palette. e.g. 128x128x0.5 bytes + 32 byte + 54 byte = 8.1kB

It is probably faster to blit a RAW binary file to the screen than to process BMP at runtime.

The sums are easy. Full colour icons take a lot of storage. Even small 32x32 icons.


Well my guess kind of would have been that you could use the 16-bit RGB565 pixel definitions as in my welcome.c file, and just read them that way from a text file on the MicroSD card and push them to screen... similar to just storing them in PROGMEM.

Or are we talking about the same thing?

Yes. If you wanted to embed the table in your Arduino Flash program memory, you use the C file. If you want a RAW binary file on SD card, you create a raw binary file on SD card. Just what the UTFT utility does.


Again, will this raw binary file contain the same pixel definitions, and will those pixel definitions be in the same 16-bit "0x0000" format, as the .c file?

What I mean is, will the raw file simply contain a succession of those 16-bit pixel definitions?