索引单色FreeType字形缓冲区中的像素

时间:2013-02-10 18:02:51

标签: freetype

我想将单色FreeType字形转换为RGBA无符号字节OpenGL纹理。像素(x,y)处的纹理颜色将是(255,255,alpha),其中

alpha = glyph->bitmap.buffer[pixelIndex(x, y)] * 255

我使用

加载我的字形
FT_Load_Char(face, glyphChar, FT_LOAD_RENDER | FT_LOAD_MONOCHROME | FT_LOAD_TARGET_MONO)

目标纹理的尺寸为glyph->bitmap.width * glyph->bitmap.rows。我已经能够使用

索引灰度字形(仅使用FT_Load_Char(face, glyphChar, FT_LOAD_RENDER)加载)
glyph->bitmap.buffer[(glyph->bitmap.width * y) + x]

虽然这在单色缓冲区上不起作用,但我最终纹理中的字符也被加扰了。

在单色字形缓冲区中获取像素(x,y)值的正确方法是什么?

3 个答案:

答案 0 :(得分:3)

基于this thread I started on Gamedev.net,我提出了以下函数来获取(x,y)处像素的填充/空状态:

bool glyphBit(const FT_GlyphSlot &glyph, const int x, const int y)
{
    int pitch = abs(glyph->bitmap.pitch);
    unsigned char *row = &glyph->bitmap.buffer[pitch * y];
    char cValue = row[x >> 3];

    return (cValue & (128 >> (x & 7))) != 0;
}

答案 1 :(得分:0)

我前段时间有一个类似的问题。所以我会尽力帮助你。

  

目标纹理的尺寸为glyph->bitmap.width * glyph->bitmap.rows

这是OpenGl非常具体的维度。如果你把它四舍五入到更好的力量会更好。

通常,您可以在每个字形的位置进行循环。然后循环从0到glyph->bitmap.rows的每一行。然后循环从0到unsigned char的行中的每个字节(glyph->pitch)。通过处理glyph->bitmap.buffer[pitch * row + i]得到字节的位置(i是内循环索引,行是外部索引)。例如:

if(s[i] == ' ') left += 20; else
    for (int row = 0; row < g->bitmap.rows; ++row) {
             if(kerning)
            for(int b = 0; b < pitch; b++){
                if(data[left + 64*(strSize*(row + 64 -  g->bitmap_top)) + b] + g->bitmap.buffer[pitch * row + b] < UCHAR_MAX)
                    data[left + 64*(strSize*(row + 64 -  g->bitmap_top)) + b] += g->bitmap.buffer[pitch * row + b];
                else
                    data[left + 64*(strSize*(row + 64 -  g->bitmap_top)) + b] = UCHAR_MAX;
            } else
        std::memcpy(data + left + 64*(strSize*(row + 64 -  g->bitmap_top)) , g->bitmap.buffer + pitch * row, pitch);
    }
    left += g->advance.x >> 6;

此代码与8位位图(标准FT_Load_Char(face, glyphChar, FT_LOAD_RENDER))相关。 现在我尝试使用单色标志,这给我带来了麻烦。所以我的答案不是你问题的解决方案。如果您只想显示该字母,那么您应该看到我的question

答案 2 :(得分:0)

以下Python函数将FT_LOAD_TARGET_MONO字形位图解包为更方便的表示形式,其中缓冲区中的每个字节映射到一个像素。

我在Python和FreeType以及我博客上的其他示例代码中获得了有关单色字体渲染的更多信息:http://dbader.org/blog/monochrome-font-rendering-with-freetype-and-python

def unpack_mono_bitmap(bitmap):
    """
    Unpack a freetype FT_LOAD_TARGET_MONO glyph bitmap into a bytearray where each
    pixel is represented by a single byte.
    """
    # Allocate a bytearray of sufficient size to hold the glyph bitmap.
    data = bytearray(bitmap.rows * bitmap.width)

    # Iterate over every byte in the glyph bitmap. Note that we're not
    # iterating over every pixel in the resulting unpacked bitmap --
    # we're iterating over the packed bytes in the input bitmap.
    for y in range(bitmap.rows):
      for byte_index in range(bitmap.pitch):

        # Read the byte that contains the packed pixel data.
        byte_value = bitmap.buffer[y * bitmap.pitch + byte_index]

        # We've processed this many bits (=pixels) so far. This determines
        # where we'll read the next batch of pixels from.
        num_bits_done = byte_index * 8

        # Pre-compute where to write the pixels that we're going
        # to unpack from the current byte in the glyph bitmap.
        rowstart = y * bitmap.width + byte_index * 8

        # Iterate over every bit (=pixel) that's still a part of the
        # output bitmap. Sometimes we're only unpacking a fraction of a byte
        # because glyphs may not always fit on a byte boundary. So we make sure
        # to stop if we unpack past the current row of pixels.
        for bit_index in range(min(8, bitmap.width - num_bits_done)):

          # Unpack the next pixel from the current glyph byte.
          bit = byte_value & (1 << (7 - bit_index))

          # Write the pixel to the output bytearray. We ensure that `off`
          # pixels have a value of 0 and `on` pixels have a value of 1.
          data[rowstart + bit_index] = 1 if bit else 0

    return data