我在理解如何在 freetype 下存储像素时遇到了麻烦,我问题的核心部分是如何在渲染字形后提取 RGB 值。
typedef uint32_t Tindex;
//
FT_Render_Glyph(face->glyph, FT_RENDER_MODE_LCD);
//
FT_Bitmap bitmap = face->glyph->bitmap;
FT_Glyph_Metrics metrics = face->glyph->metrics;
//
Tindex colStartPos = metrics.horiBearingX >> 6;
Tindex rowStartPos = metrics.horiBearingY >> 6;
//
for (Tindex y = 0; y < bitmap.rows; y = y + 3)
{
Tindex row = rowStartPos + y;
for (Tindex x = 0; x < bitmap.width; x = x + 3)
{
Tindex col = colStartPos + x;
uint8_t r = bitmap.buffer[y * bitmap.width + x];
uint8_t g = bitmap.buffer[y * bitmap.width + x + 1];
uint8_t b = bitmap.buffer[y * bitmap.width + x + 2];
img(col, row) = pixel{r, g, b, 255};
// img and pixel are placeholders to simplify the code
}
}
官方文档没有指定像素的存储方式,它只是说格式是 RGB,我的编译器也说从
bitmap.buffer
检索的值的类型是 float
但这可能是某种类型双关技术的结果。我确实注意到在
FT_RENDER_MODE_LCD
中渲染时,迭代次数是三次重复,所以数学检查出来了,但我不明白我做错了什么,这个片段只是我做过的许多尝试之一。另请注意,在我的情况下
bitmap.pitch / bitmap.rows
等于 1
,我希望它是 3
。有人可以解释我应该如何读取像素值?可以切换到 RGBA 格式吗?
从文档看起来格式是交错的,但看起来不是那样
这段代码使用了 boost、libpng 和 freetype,它重现了我遇到的问题并且它是独立的(不要忘记自定义 ttf 字体的路径)
#include <boost/gil/gil_all.hpp>
#include <boost/gil/extension/io/png_dynamic_io.hpp>
extern "C" {
#define FT_CONFIG_OPTION_SUBPIXEL_RENDERING
#include <ft2build.h>
#include FT_FREETYPE_H
#include <ftlcdfil.h>
}
#include <cstdint>
#define FONTFILE "/tmp/DroidSans.ttf"
#define IMGSIZE 400
typedef uint32_t Tindex;
int main()
{
FT_Library library = 0;
FT_Face face = 0;
FT_Init_FreeType(&library);
FT_Library_SetLcdFilter(library, FT_LCD_FILTER_LIGHT);
FT_New_Face(library, FONTFILE, 0, &face);
FT_Set_Char_Size(face, 0, 24 * 64, 300, 300);
FT_ULong charcode = 0x003f;
FT_UInt glyph_index = 0;
glyph_index = FT_Get_Char_Index(face, charcode);
FT_Load_Glyph(face, glyph_index, FT_LOAD_TARGET_NORMAL);
FT_Render_Glyph(face->glyph, FT_RENDER_MODE_LCD);
FT_Bitmap bitmap = face->glyph->bitmap;
FT_Glyph_Metrics metrics = face->glyph->metrics;
Tindex colStartPos = metrics.horiBearingX / 64;
Tindex rowStartPos = metrics.horiBearingY / 64;
boost::gil::rgba8_image_t img{IMGSIZE, IMGSIZE};
boost::gil::rgba8_image_t::view_t imgView{boost::gil::view(img)};
for (Tindex y = 0; y < bitmap.rows; y++)
{
Tindex row = rowStartPos + y;
for (Tindex x = 0; x < bitmap.width; x++)
{
Tindex col = colStartPos + x;
uint8_t r = bitmap.buffer[y * bitmap.pitch + x * 3];
uint8_t g = bitmap.buffer[y * bitmap.pitch + x * 3 + 1];
uint8_t b = bitmap.buffer[y * bitmap.pitch + x * 3 + 2];
imgView(col, row) = boost::gil::rgba8_pixel_t{r, g, b, 255};
}
}
boost::gil::png_write_view("img.png", imgView);
}
我编译这个
g++ -std=c++11 $(freetype-config --cflags) main.cpp -lpng $(freetype-config --libs)
最佳答案
来自文档的 AFAIU ( http://www.freetype.org/freetype2/docs/reference/ft2-basic_types.html#FT_Bitmap ) 你的循环应该是这样的:
for (Tindex y = 0; y < bitmap.rows; y++)
{
Tindex row = rowStartPos + y;
for (Tindex x = 0; x < bitmap.width; x++)
{
Tindex col = colStartPos + x;
uint8_t r = bitmap.buffer[y * bitmap.pitch + x*3];
uint8_t g = bitmap.buffer[y * bitmap.pitch + x*3 + 1];
uint8_t b = bitmap.buffer[y * bitmap.pitch + x*3 + 2];
img(col, row) = pixel{r, g, b, 255};
// img and pixel are placeholders to simplify the code
}
}
关于c++ - freetype 中的 RGB 像素格式,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23982261/