简体   繁体   English

将 Freetype 位图复制到 Magick::Image 中的特定偏移量

[英]Copy Freetype Bitmap into Magick::Image at specific offset

In my game engine, I have a texture loading API which wraps low level libraries like OpenGL, DirectX, etc. This API uses Magick++ because I found it to be a convenient cross-platform solution and allows me to create procedural textures fairly easily.在我的游戏引擎中,我有一个纹理加载 API,它包装了 OpenGL、DirectX 等低级库。这个 API 使用 Magick++,因为我发现它是一个方便的跨平台解决方案,并且允许我相当轻松地创建程序纹理。

I'm now adding a text rendering system using freetype where I want to use this texture API to dynamically generate a texture atlas for any given font where all the glyphs are stored horizontally adjacent.我现在正在添加一个使用 freetype 的文本渲染系统,我想使用这个纹理 API 为所有字形水平相邻存储的任何给定字体动态生成纹理图集。

I have been able to get this to work in the past by buffering the bitmaps directly into OpenGL.过去,我可以通过将位图直接缓冲到 OpenGL 中来实现这一点。 But now I want to accomplish this in a platform independent way, using this API.但现在我想使用此 API 以独立于平台的方式完成此操作。

I've looked around for a few examples but I can't find anything quite like what I'm after so if there are any magick++ experts around, I'd really appreciate some pointers.我四处寻找一些示例,但找不到与我所追求的完全相似的东西,因此如果周围有任何 magick++ 专家,我将非常感谢一些指示。

So in simple terms: I've got a freetype bitmap and I want to be able to copy its pixel buffer to a specific offset inside a Magick::Image.所以简单来说:我有一个自由类型位图,我希望能够将其像素缓冲区复制到 Magick::Image 内的特定偏移量。

This code might help to clarify:此代码可能有助于澄清:

auto texture = e6::textures->create(e6::texture::specification{}, [name, totalWidth, maxHeight](){

      // Initialises Freetype
      FT_Face face;
      FT_Library ft;

      if (FT_Init_FreeType(&ft)) {
        std::cout << "ERROR::FREETYPE: Could not init FreeType Library" << std::endl;
      }

      if (int error = FT_New_Face(ft, path(name.c_str()).c_str(), 0, &face)) {
        std::cout << "Failed to initialise fonts: " << name << std::endl;
        throw std::exception();
      }

      // Sets the size of the font
      FT_Set_Pixel_Sizes(face, 0, 100);

      unsigned int cursor = 0; // Keeps track of the horizontal offset.

      // Preallocate an image buffer
      // totalWidth and maxHeight is the size of the entire atlas
      Magick::Image image(Magick::Geometry(totalWidth, maxHeight), "BLACK");
      image.type(Magick::GrayscaleType);
      image.magick("BMP");
      image.depth(8);
      image.modifyImage();
      Magick::Pixels view(image);

      // Loops through a subset of the ASCII codes
      for (uint8_t c = 32; c < 128; c++) {
        if (FT_Load_Char(face, c, FT_LOAD_RENDER)) {
          std::cout << "Failed to load glyph: " << c << std::endl;
          continue;
        }

        // Just for clarification...
        unsigned int width = face->glyph->bitmap.width;
        unsigned int height = face->glyph->bitmap.rows;
        unsigned char* image_data = face->glyph->bitmap.buffer;

        // This is the problem part.
        // How can I copy the image_data into `image` at the cursor position?

        cursor += width; // Advance the cursor
      }

      image.write(std::string(TEXTURES) + "font-test.bmp"); // Write to filesystem

      // Clean up freetype
      FT_Done_Face(face);
      FT_Done_FreeType(ft);

      return image;
    }, "font-" + name);

I tried using a pixel cache which the documentation demonstrates:我尝试使用文档演示的像素缓存:

Magick::Quantum *pixels = view.get(cursor, 0, width, height);
*pixels = *image_data;
view.sync();

But this leaves me with a completely black image, I think because the image_data goes out of scope.但这给我留下了一个完全黑色的图像,我认为是因为 image_data 超出了范围。

I was hoping there'd be a way to modify the image data directly but after a lot of trial and error, I ended up just creating an image for each glyph and compositing them together:我希望有一种方法可以直接修改图像数据,但经过大量试验和错误后,我最终只是为每个字形创建了一个图像并将它们合成在一起:

...

Magick::Image glyph (Magick::Geometry(), "BLACK");
glyph.type(MagickCore::GrayscaleType);
glyph.magick("BMP");
glyph.depth(8);
glyph.read(width, height, "R", Magick::StorageType::CharPixel, image_data);

image.composite(glyph, cursor, 0);

cursor += width;

At the very least, I hope this helps to prevent someone else going down the same rabbit hole I did.至少,我希望这有助于防止其他人落入我做过的同一个兔子洞。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM