我很难理解像素在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格式吗?
从文档中看,格式为 interleaved ,但它看起来不像
这段代码使用了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)
答案 0 :(得分:1)
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
}
}
答案 1 :(得分:0)
documentation表示默认FT_PIXEL_MODE_GRAY
每个像素存储在1个字节中,表示灰色阴影。您可以手动将其转换为RGBA,也可以使用某些Freetype功能,例如FT_PIXEL_MODE_LCD
或FT_Bitmap_Convert()
。我自己也没试过。