我想将单色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)值的正确方法是什么?
答案 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