我在理解如何在 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/

10-11 17:04