Bitmap Font data as array in C
You can use convert
as shown here: C header file with bitmapped fonts
Probably there are a lot of commands to convert fonts to bitmap, but the freetype API is easy enough to write your own with not much code.
Using the freetype example I wrote something you can use as a start, it output an .xbm
file (is a c
file but you can use graphics programs like gimp
to view/edit it).
Notiche that gimp
also support export to .xbm
with different bytes per pixel.
The .xbm
exported by the example is a 1 bit per pixel format (1 black, 0 white), you need to edit the code in order to handle more colors (the freetype normally use a 8 bit gray scale bitmap buffer to render, if render mode is FT_RENDER_MODE_NORMAL
, you may also need to remove the step with the temporary bitmap used to align the FT buffer to 1 byte).
The to_bitmap
function is where the conversion from the FT buffer to the destination bitmap is done,
To build the example the freetype
dev package is needed, on Debian
(maybe also Ubuntu
) use:
sudo apt-get install libfreetype6-dev
Simply make
to build it.
Use the command with the font path as argument, the output is on stdout
./font2c /usr/share/fonts/X11/misc/9x15-ISO8859-1.pcf.gz >c-bmp-font.xbm
Makefile
:
CFLAGS += -O2 -Wall
CFLAGS += $(shell freetype-config --cflags)
LIBS += $(shell freetype-config --libs)
font2c: font2c.c
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
clean:
-rm -f font2c
font2c.c
:
#include <stdio.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include <ftbitmap.h>
#define WIDTH 640
#define BYTEWIDTH (WIDTH)/8
#define HEIGHT 480
static unsigned char image[HEIGHT][BYTEWIDTH];
static FT_Library library;
static FT_Face face;
static FT_Error err;
static FT_Bitmap tempbitmap;
static void to_bitmap( FT_Bitmap* bitmap, FT_Int x, FT_Int y) {
FT_Int i, j, p, q;
FT_Int x_max = x + bitmap->width;
FT_Int y_max = y + bitmap->rows;
for ( i = x, p = 0; i < x_max; i++, p++ ) {
for ( j = y, q = 0; j < y_max; j++, q++ ) {
if ( (i < 0) || (j < 0) || (i >= WIDTH || j >= HEIGHT) )
continue;
image[j][i >> 3] |= (bitmap->buffer[q * bitmap->width + p]) << (i & 7);
}
}
}
static void draw_glyph(unsigned char glyph, int *x, int *y) {
FT_UInt glyph_index;
FT_GlyphSlot slot = face->glyph;
glyph_index = FT_Get_Char_Index( face, glyph );
if ((err = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT ))) {
fprintf( stderr, "warning: failed FT_Load_Glyph 0x%x %d\n", glyph, err);
return;
}
if ((err = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_MONO ))) {
fprintf( stderr, "warning: failed FT_Render_Glyph 0x%x %d\n", glyph, err);
return;
}
FT_Bitmap_New(&tempbitmap);
FT_Bitmap_Convert( library, &slot->bitmap, &tempbitmap, 1);
to_bitmap( &tempbitmap, *x, *y );
FT_Bitmap_Done( library, &tempbitmap );
*x += slot->advance.x >> 6;
}
static void out_xbm(int w, int h) {
int x, y;
printf("#define BMP_width %d\n", WIDTH);
printf("#define BMP_height %d\n", h);
printf("static char BMP_bits[] = {\n");
for (y=0; y < h; y++) {
printf("\t");
for (x=0; x < w; x++) {
printf("0x%x, ", image[y][x]);
}
printf("\n");
}
printf("\n}\n");
}
int main(int argc, char **argv) {
char *filename;
int x = 0, y = 0;
int g;
memset (image, 0, BYTEWIDTH*HEIGHT);
if (argc < 2) {
fprintf( stderr, "usage: font2c [font]\n");
exit(1);
}
filename = argv[1];
if ((err = FT_Init_FreeType( &library ))) {
fprintf( stderr, "error: Init_Freetype failed %d\n", err);
exit(1);
}
if ((err = FT_New_Face( library, filename, 0, &face ))) {
fprintf( stderr, "error: FT_New_Face failed %d\n", err);
exit(1);
}
for (g = 0; g < 256; g++) {
if (x+8 >= WIDTH) {
x = 0;
y += 15; // FIXME get ascender
}
draw_glyph(g, &x, &y);
}
out_xbm(BYTEWIDTH, HEIGHT);
FT_Done_Face( face );
FT_Done_FreeType( library );
return 0;
}
It's quite easy to convert PSF (console) font to C include rather PCF (X11). I think it will do the trick for you if you're looking for monospace bitmap font for simple embedded applications.
All you need is psf2inc
from psftools
package:
$ psf2inc --psf1 font.psf font.inc
Now font.inc
holding all 256 ASCII characters:
0x36, 0x04, /* Magic */
0x02, /* Type */
0x0e, /* Char size */
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe,
0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, /* 0 */
0x00, 0x00, 0xfc, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6,
0xc6, 0xc6, 0xc6, 0xfc, 0x00, 0x00, /* 1 */
0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xc6, 0xfc, 0xc6,
0xc6, 0xc6, 0xc6, 0xfc, 0x00, 0x00, /* 2 */
And so on. After some editing you will get a nice header with monospace font.