将单色FreeType位图转换为8位像素数组

时间:2018-08-28 23:16:14

标签: c++ freetype2

我花了几个小时试图将FreeType生成的单色位图转换为每个像素使用8位的像素数组(以便我可以将它们用作OpenGL的alpha值)。我知道我可以得到一个普通的8bpp位图并使用它,但是我确实需要单色版本。而且我已经尝试了对像素进行阈值处理的方法,但是结果一点也不令人满意。看来,一旦有了抗锯齿版本,就无法返回。

下面的代码段是我现在拥有的代码,除了几个字母外,它实际上几乎可以正常工作。

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;
}

以下是输出:

enter image description here

我试图弄清楚扭曲的字母的共同点(也许可以帮到我),但我不知道。

真的,我不知道我的操作方式出了什么问题。但是一定有我想念的东西。更改字体并不能解决问题(除了扭曲与以前不同的字母之外)。

编辑:我注意到face->glyph->bitmap.widthface->glyph->bitmap.rows有时返回的值与face->glyph->metrics.width / 64face->glyph->metrics.height / 64略有不同。我尝试过切换它们,并且渲染效果肯定更好,但是仍然有些字符(例如Arial中的“ t”和“ g”,Microsoft Sans Serif中的“ X”和“ 0”)有点移位或变形。

Arial: enter image description here

Microsoft Sans Serif: enter image description here

这真的很奇怪,我必须丢失一些东西,因为我不认为这是一个错误。 FreeType似乎对于库而言过于牢固和可靠。此外,将字体加载为非单色可以很好地工作,因此呈现字符串的代码不是问题。

1 个答案:

答案 0 :(得分:0)

一行中的字节数不一定是适合该行中位数的最小数,而是在位图的pitch字段中报告。