Distorted freetype fonts

Started by
14 comments, last by GreyHound 13 years, 1 month ago
Hi!

I'm trying to load and display a character bitmap rendered by the freetype library.

FT_Library library;if (FT_Init_FreeType(&library)) {	LogManager::GetInstance()->LogMessage("Could not initialize FreeType library.", LL_ERROR);	return 0;}FT_Face face;unsigned int error;error = FT_New_Face(library, "tests/font/arialbd.ttf", 0, &face);if (error == FT_Err_Unknown_File_Format) {	LogManager::GetInstance()->LogMessage("Unknown file format.", LL_ERROR);} else if (error) {	LogManager::GetInstance()->LogMessage("Could not load font file.", LL_ERROR);}error = FT_Set_Char_Size(face, 25 << 6, 25 << 6, 96, 96);FT_Load_Glyph(face, FT_Get_Char_Index(face, 'A'), FT_LOAD_RENDER);FT_Bitmap& bitmap = face->glyph->bitmap;unsigned char* bitmapBuffer = new unsigned char[bitmap.width * bitmap.rows];for (unsigned int i = 0; i < bitmap.rows; i++) {	for (unsigned int j = 0; j < bitmap.width; j++) {		bitmapBuffer[j + i * bitmap.width] = bitmap.buffer[j + i * bitmap.width];	}}

The above code initializes the freetype library and loads a character in ('A' in this case).
After that, it gets the glyph's bitmap dimensions and allocates a buffer to store the glyph image.
Unfortunately, all I get is a distorted version of the character, as you can see from the following picture:


The weird thing is that for some other characters, it works just fine:


I really can't figure out what's wrong.

Thanks in advance!
Advertisement
Looks like your rows are too tight for some characters. My bet is that for these characters the width is NOT a multiple of four and is rounded down to satisfy width % 4 == 0

I don't see it at one glance, I find freetype a little cumbersome in this respect, but what you must do is debug (write to a log) the character you're printing, width, height, pitch, ... all metrics. And see what is different for bad glyphs over good glyphs.

One thing to note, is that you should use pitch for row offsets from the destination (from FT).
bitmapBuffer[j + i * bitmap.width] = bitmap.buffer[j + i * bitmap.pitch];

Keep the other widths the same, it should be good like this.

EDIT: looking closer, it looks like your B is up-side-down!
[size="2"]SignatureShuffle: [size="2"]Random signature images on fora
Could be the bitmap's width is different from its pitch?
bitmapBuffer[j + i * bitmap.width] = bitmap.buffer[j + i * bitmap.pitch];
Does that help?

EDIT: Beaten :(

EDIT2:
Quote:Original post by Decrius
EDIT: looking closer, it looks like your B is up-side-down!

I think Freetype stores its bitmaps with the origin in the lower-left, so you need to reverse the row order to get things right-side-up... either that or some other bit of what he's doing acts that way... it's always so hard to keep straight which libraries keep their origin where once I already have "black box" code that just deals with it all for me, but it's upside down because of that I'd bet.
Yes, the B is up-side-down, as Shinkage said, the problem is the way freetype stores bitmaps. Not really a problem indeed, just have to reverse the rows.

However, using pitch instead of width doesn't solve the issue. It seems that for some characters the buffer size doesn't match width * rows (or width * pitch). It's like freetype uses a fixed width/height for all glyphs and uses that one for all the others. I'm going to do some debug and update as soon as possible.
Ok, wrote a little program to check bitmaps that don't look right, here the results:

A - WRONGbitmap width	: 37bitmap rows	: 38bitmap pitch	: 37B - CORRECTbitmap width	: 32bitmap rows	: 38bitmap pitch	: 32C - WRONGbitmap width	: 33bitmap rows	: 39bitmap pitch	: 33D - CORRECTbitmap width	: 32bitmap rows	: 38bitmap pitch	: 32E - CORRECTbitmap width	: 28bitmap rows	: 38bitmap pitch	: 28F - WRONGbitmap width	: 25bitmap rows	: 38bitmap pitch	: 25G - CORRECTbitmap width	: 36bitmap rows	: 40bitmap pitch	: 36H - WRONGbitmap width	: 30bitmap rows	: 38bitmap pitch	: 30I - WRONGbitmap width	: 7bitmap rows	: 38bitmap pitch	: 7J - CORRECTbitmap width	: 24bitmap rows	: 39bitmap pitch	: 24K - WRONGbitmap width	: 34bitmap rows	: 38bitmap pitch	: 34L - WRONGbitmap width	: 26bitmap rows	: 38bitmap pitch	: 26M - WRONGbitmap width	: 35bitmap rows	: 38bitmap pitch	: 35N  - WRONGbitmap width	: 30bitmap rows	: 38bitmap pitch	: 30O  - WRONGbitmap width	: 37bitmap rows	: 40bitmap pitch	: 37P - WRONGbitmap width	: 29bitmap rows	: 38bitmap pitch	: 29Q - WRONGbitmap width	: 38bitmap rows	: 43bitmap pitch	: 38R - WRONGbitmap width	: 34bitmap rows	: 38bitmap pitch	: 34S - WRONGbitmap width	: 30bitmap rows	: 40bitmap pitch	: 30T - WRONGbitmap width	: 29bitmap rows	: 38bitmap pitch	: 29U - WRONGbitmap width	: 30bitmap rows	: 39bitmap pitch	: 30V - WRONGbitmap width	: 35bitmap rows	: 38bitmap pitch	: 35W - WRONGbitmap width	: 49bitmap rows	: 38bitmap pitch	: 49X - WRONGbitmap width	: 35bitmap rows	: 38bitmap pitch	: 35Y - WRONGbitmap width	: 35bitmap rows	: 38bitmap pitch	: 35Z - WRONGbitmap width	: 30bitmap rows	: 38bitmap pitch	: 30

So I think you are right Decrius, bitmaps' widths should be aligned to the nearest largest multiple of 4, shouldn't they?
Quote:Original post by Taylor001
However, using pitch instead of width doesn't solve the issue. It seems that for some characters the buffer size doesn't match width * rows (or width * pitch). It's like freetype uses a fixed width/height for all glyphs and uses that one for all the others. I'm going to do some debug and update as soon as possible.


Are you sure that you're not accidentally using the pitch when writing into the memory buffer you allocated yourself?

Besides the pitch thing I can't see what should be wrong with your code, although I don't understand why your glyphs are coming out upside down - in my freetype code I certainly don't flip them and it works fine.

Can you post how your code looks after you changed the pitch thing?

Have you tried printing your glyphs to stdout with printf() to verify that the problem isn't later in your rendering pipeline?
Quote:Original post by rneckelmann
Quote:Original post by Taylor001
However, using pitch instead of width doesn't solve the issue. It seems that for some characters the buffer size doesn't match width * rows (or width * pitch). It's like freetype uses a fixed width/height for all glyphs and uses that one for all the others. I'm going to do some debug and update as soon as possible.


Are you sure that you're not accidentally using the pitch when writing into the memory buffer you allocated yourself?

Besides the pitch thing I can't see what should be wrong with your code, although I don't understand why your glyphs are coming out upside down - in my freetype code I certainly don't flip them and it works fine.

Can you post how your code looks after you changed the pitch thing?

Have you tried printing your glyphs to stdout with printf() to verify that the problem isn't later in your rendering pipeline?


The new pitched code looks like this:

for (unsigned int i = 0; i &lt; bitmap.rows; i++) {	for (unsigned int j = 0; j &lt; bitmap.width; j++) {		bitmapBuffer[j + i * bitmap.width] = bitmap.buffer[j + i * bitmap.pitch];	}}


Bitmap rendering is done through a call to glDrawPixels(bitmap.width, bitmap.height, GL_LUMINANCE, GL_UNSIGNED_BYTE, bitmapBuffer);
Quote:Bitmap rendering is done through a call to glDrawPixels(bitmap.width, bitmap.height, GL_LUMINANCE, GL_UNSIGNED_BYTE, bitmapBuffer);


Ah, okay, that atleast explains the flipping :P.

I looked at my old code again and saw that I'm using FT_Set_Pixel_Sizes() to specify the size of my font in screen pixels in contrary to your FT_Set_Char_Size() which works in device units.

For the individual glyphs I calculate the width and height in pixels:

int nWidth = SomeFace->glyph->metrics.width / 64;int nHeight = SomeFace->glyph->metrics.height / 64;


I guess you can fix your problem by doing something similar, although I have no clue why FT_Set_Char_Size() isn't producing the same results. (It's probably related to your glyph dimensions ending up as non-integer for some specific glyphs...)

[Edited by - rneckelmann on August 27, 2010 6:35:27 PM]
Tried switching to FT_Set_Pixel_Sizes but result is the same.
bitmap.rows/width and metrics.width/height >> 6 produce the same results, so, nothing changes. :\
Quote:Original post by Taylor001
Tried switching to FT_Set_Pixel_Sizes but result is the same.
bitmap.rows/width and metrics.width/height >> 6 produce the same results, so, nothing changes. :\


Very strange. Someone above mentioned something about multiple of 4. Tried snapping your glyph sizes to that?

Otherwise try to grab one of the tutorials from freetype.org and slowly change it into what you got now - and check when it stops to work :P

This topic is closed to new replies.

Advertisement