lexus2k / lcdgfx

Driver for LCD displays running on Arduino/Avr/ESP32/Linux (including Rasperry) platforms
MIT License
377 stars 52 forks source link

How to reduce font file size? #59

Closed seramonte closed 3 years ago

seramonte commented 3 years ago

For example, I would like to use the included comic_sans font in font.c, but I only need the numbers and space characters, and would like to reduce memory use. How do I remove the unwanted characters so that the font will still work? If I simply remove the not needed arrays, the font won't work. Is there another adjustment that needs to be made? Thanks.

lexus2k commented 3 years ago

Hi,

You can try to generate new font: https://github.com/lexus2k/lcdgfx/wiki/How-to-create-new-font-for-the-library Just specify the range of a symbols, you need.

Refer to section Variable width fonts

seramonte commented 3 years ago

Thanks, I had previously viewed that information. Although one can specify a range, one apparently cannot specify a non-contiguous set of characters, for example: " ", ".", 0-9, "v", "a", "w", without adjusting something else in the file format to make it work. So, is it possible? If so, how? Thanks.

lexus2k commented 3 years ago

Well,

regarding font format: Each format for storing font data has some overhead, the overhead depends on what and how the format allows to store inside. Freefont format is described here. The format has overhead for each block of chars: 3 bytes + N * 4 bytes, where N is the number of characters in the block. Even in case of some new format you need to store information on char width, height, char location inside the font binary data (offset), and if you want to have completely non-contiguous set, the char unicode (2 bytes). Yes, maybe you will win the space in flash for chars bitmaps, but you will loose on char overhead definitely, and it will take your time and effort to achieve desired results. It's not worth it.

  1. One of the solutions for your case is to use micro controller with bigger flash size and SRAM (you didn't mention yours).
  2. Another Simple solution, the Free Font format of lcdgfx library allows to create fonts with multiple char ranges.

This is what I'm talking about:

./fontgenerator.py -s 8 -g 0 9 -g v 0 -g a 0 --ttf calibri.ttf

The output has 3 groups of chars: 0-9, 'v', 'a'

extern const uint8_t free_calibri6x7[] PROGMEM;
const uint8_t free_calibri6x7[] PROGMEM =
{
//  type|width|height|first char
    0x02, 0x06, 0x07, 0x00,
// GROUP first '0' total 10 chars
//  unicode(LSB,MSB)|count
    0x00, 0x30, 0x0A, // unicode record
    0x00, 0x00, 0x05, 0x07,// char '0' (0x0030/48)
    0x00, 0x05, 0x04, 0x07,// char '1' (0x0031/49)
    0x00, 0x09, 0x04, 0x07,// char '2' (0x0032/50)
    0x00, 0x0D, 0x04, 0x07,// char '3' (0x0033/51)
    0x00, 0x11, 0x05, 0x07,// char '4' (0x0034/52)
    0x00, 0x16, 0x04, 0x07,// char '5' (0x0035/53)
    0x00, 0x1A, 0x04, 0x07,// char '6' (0x0036/54)
    0x00, 0x1E, 0x04, 0x07,// char '7' (0x0037/55)
    0x00, 0x22, 0x05, 0x07,// char '8' (0x0038/56)
    0x00, 0x27, 0x05, 0x07,// char '9' (0x0039/57)
    0x00, 0x2C,
    0x1C, 0x63, 0x41, 0x41, 0x3E, // char '0' (0x0030/48)
    0x42, 0x41, 0x7F, 0x40, // char '1' (0x0031/49)
    0x63, 0x51, 0x4B, 0x46, // char '2' (0x0032/50)
    0x49, 0x49, 0x4F, 0x32, // char '3' (0x0033/51)
    0x10, 0x1C, 0x12, 0x7F, 0x10, // char '4' (0x0034/52)
    0x4F, 0x49, 0x49, 0x31, // char '5' (0x0035/53)
    0x7E, 0x49, 0x49, 0x39, // char '6' (0x0036/54)
    0x01, 0x71, 0x0D, 0x03, // char '7' (0x0037/55)
    0x20, 0x57, 0x49, 0x49, 0x76, // char '8' (0x0038/56)
    0x04, 0x4B, 0x49, 0x69, 0x3E, // char '9' (0x0039/57)
// GROUP first 'v' total 1 chars
//  unicode(LSB,MSB)|count
    0x00, 0x76, 0x01, // unicode record
    0x00, 0x00, 0x05, 0x07,// char 'v' (0x0076/118)
    0x00, 0x05,
    0x04, 0x38, 0x40, 0x38, 0x04, // char 'v' (0x0076/118)
// GROUP first 'a' total 1 chars
//  unicode(LSB,MSB)|count
    0x00, 0x61, 0x01, // unicode record
    0x00, 0x00, 0x04, 0x07,// char 'a' (0x0061/97)
    0x00, 0x04,
    0x20, 0x54, 0x54, 0x7C, // char 'a' (0x0061/97)
    0x00, 0x00, 0x00, // end of unicode tables
    // FONT REQUIRES 123 BYTES
};
seramonte commented 3 years ago

Thank you, I had not seen the ability to select groups. But now I get an error:

~/Arduino/libraries/lcdgfx/tools$ python fontgenerator.py -s 8 -g 0 0 -g 0 9 -g v 0 -g a 0 --ttf /usr/share/fonts/truetype/ubuntu/Ubuntu-B.ttf > Ubuntu_B.h Traceback (most recent call last): File "fontgenerator.py", line 187, in <module> font.generate_new_format() TypeError: generate_new_format() takes exactly 3 arguments (1 given)

I reinstalled ver. 1.1.0 from .zip file. The install 1.1.0 from arduino IDE was missing the /tools dir. I also did: sudo pip install freetype-py

lexus2k commented 3 years ago

Please, try to rename the font and to avoid using - char. Filename is the root cause.

seramonte commented 3 years ago

Thank you, I changed the name and tried the following: ~/Arduino/libraries/lcdgfx/tools$ python fontgenerator.py -s 8 -g 0 0 -g 0 9 -g v w -g a 0 -f new --ttf UbuntuMonoB.ttf > UbuntuMonoB.h Traceback (most recent call last): File "fontgenerator.py", line 187, in <module> font.generate_new_format() TypeError: generate_new_format() takes exactly 3 arguments (1 given)

lexus2k commented 3 years ago

Is it python 2.7 or 3?

seramonte commented 3 years ago

Thank you, It's Python 2.7.17

lexus2k commented 3 years ago

I've tried the same command as yours both for Python3 and Python2, and there is no issue. Moreover, the line number 187, provided in your post, points to empty line. Can you download latest changes from the master branch and try one more time?

seramonte commented 3 years ago

I did as you suggested, and voila`, it worked this time! Fantastic! It's exactly what I was looking for. Thank you so much!

lexus2k commented 3 years ago

I'm glad that it works. Thank you for the testing.

lexus2k commented 3 years ago

I've released version 1.1.1. Soon it will become available via Arduino Manager.