我花了几个小时来尝试将由FreeType生成的单色位图转换为每像素使用8位的像素数组(以便我可以将它们用作OpenGL的alpha值)。我知道我可以只得到普通的8bpp位图并使用它,但我真的需要单色版本。我已经尝试过阈值化像素的方法,但结果并不令人满意。似乎一旦你有了抗锯齿版本,就无法回去了。
下面的代码片段是我现在拥有的,它非常接近完美,只有几个字母有问题。
这是输出结果:
我试图找出扭曲字母的共同点(也许这可以帮助我),但我不知道。
实际上,我不知道我做这件事情的方式有什么问题。但肯定有些东西我漏了。更改字体不能解决问题(除了扭曲不同的字母)。
编辑:我注意到face->glyph->bitmap.width和face->glyph->bitmap.rows有时会返回与face->glyph->metrics.width / 64和face->glyph->metrics.height / 64稍微不同的值。我尝试交换它们,渲染肯定更好,但仍然有一些字符(例如Arial的't'和'g',以及Microsoft Sans Serif的'X'和'0')有点偏移或扭曲。
Arial: https://istack.dev59.com/1DJnf.webp Microsoft Sans Serif: https://istack.dev59.com/027hs.webp 这真的很奇怪,我必须漏掉了什么,因为我不相信这是一个bug。FreeType似乎是一个非常可靠的库。此外,将字体加载为非单色工作得非常完美,因此这不是呈现字符串的代码的问题。
下面的代码片段是我现在拥有的,它非常接近完美,只有几个字母有问题。
if (FT_Load_Glyph(face, glyphIndex, FT_LOAD_MONOCHROME | FT_LOAD_TARGET_MONO))
throw exception();
if (FT_Render_Glyph(face->glyph, FT_RENDER_MODE_MONO))
throw exception();
const Size bitmapSize = Size(
face->glyph->metrics.width / 64, face->glyph->metrics.height / 64
);
u8 *bitmapBits = face->glyph->bitmap.buffer;
u8 *bitmapBytes = new u8[bitmapSize.width * bitmapSize.height];
memset(bitmapBytes, 0, bitmapSize.width * bitmapSize.height);
int width = face->glyph->bitmap.width;
int height = face->glyph->bitmap.rows;
const u8 *src = bitmapBits;
for (int row = 0; row < height; ++row)
{
u8 *dst = &bitmapBytes[row * width];
for (int col = 0; col < width / 8; ++col)
{
u8 byte = src[col];
*dst++ = ((byte & (1 << 7)) != 0) ? 255: 0;
*dst++ = ((byte & (1 << 6)) != 0) ? 255: 0;
*dst++ = ((byte & (1 << 5)) != 0) ? 255: 0;
*dst++ = ((byte & (1 << 4)) != 0) ? 255: 0;
*dst++ = ((byte & (1 << 3)) != 0) ? 255: 0;
*dst++ = ((byte & (1 << 2)) != 0) ? 255: 0;
*dst++ = ((byte & (1 << 1)) != 0) ? 255: 0;
*dst++ = ((byte & (1 << 0)) != 0) ? 255: 0;
}
u8 trailingByte = src[width / 8];
int i = 7;
switch (width % 8)
{
case 7: *dst++ = ((trailingByte & (1 << (i--))) != 0) ? 255 : 0;
case 6: *dst++ = ((trailingByte & (1 << (i--))) != 0) ? 255 : 0;
case 5: *dst++ = ((trailingByte & (1 << (i--))) != 0) ? 255 : 0;
case 4: *dst++ = ((trailingByte & (1 << (i--))) != 0) ? 255 : 0;
case 3: *dst++ = ((trailingByte & (1 << (i--))) != 0) ? 255 : 0;
case 2: *dst++ = ((trailingByte & (1 << (i--))) != 0) ? 255 : 0;
case 1: *dst++ = ((trailingByte & (1 << (i--))) != 0) ? 255 : 0;
case 0: break;
}
src += face->glyph->bitmap.pitch;
}
这是输出结果:
我试图找出扭曲字母的共同点(也许这可以帮助我),但我不知道。
实际上,我不知道我做这件事情的方式有什么问题。但肯定有些东西我漏了。更改字体不能解决问题(除了扭曲不同的字母)。
编辑:我注意到face->glyph->bitmap.width和face->glyph->bitmap.rows有时会返回与face->glyph->metrics.width / 64和face->glyph->metrics.height / 64稍微不同的值。我尝试交换它们,渲染肯定更好,但仍然有一些字符(例如Arial的't'和'g',以及Microsoft Sans Serif的'X'和'0')有点偏移或扭曲。
Arial: https://istack.dev59.com/1DJnf.webp Microsoft Sans Serif: https://istack.dev59.com/027hs.webp 这真的很奇怪,我必须漏掉了什么,因为我不相信这是一个bug。FreeType似乎是一个非常可靠的库。此外,将字体加载为非单色工作得非常完美,因此这不是呈现字符串的代码的问题。