ぬの部屋(仮)
nu-no-he-ya
  •   12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
    1234567
    891011121314
    15161718192021
    22232425262728
           
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
         12
    3456789
    10111213141516
    17181920212223
    242526272829 
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
        123
    45678910
    11121314151617
    18192021222324
    25262728   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    15161718192021
    293031    
           
         12
    3456789
    10111213141516
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728     
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
          1
    2345678
    9101112131415
    16171819202122
    232425262728 
           
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
  • FreeType2を試す-5- 一行のテキストを出力

    文字列を画像として出力する。

    仕組みとしては、画像と高さ、幅情報、移動量情報を全て配列にし、一行分描画してから高さ計算を行う。

    #pragma once
    
    #include <ft2build.h>
    #include FT_FREETYPE_H
    
    #include <freetype/ftbitmap.h>
    
    #include <vector>
    
    
    // 人文字の画像とサイズ・位置の情報
    struct charpict {
      std::vector<char> m_pic;
      int width;
      int height;
      int left;
      int top;
      int advancex;
      int advancey;
    };
    // 文字列をラスタライズするクラス
    class SingleLineText {
      std::vector<charpict> m_pict;
    
      int imageWidth; //!< 結果画像の幅
      int imageHeight;//!< 結果画像の高さ
      std::vector<unsigned char> m_image;//!< 結果画像
    
      FT_Library* m_plib;
      FT_Face face;      // handle to face object
      //! @brief m_imageに書き込むための座標計算関数
      //! @param [in] x 二次元座標のx
      //! @param [in] y 二次元座標のy
      //! @return 一次元配列のindex
      int pixel_pos(const int x, const int y) {
        return y * imageWidth + x;
      }
      //! @brief 作成済みの一文字の画像を全体画像に書き込む
      //! @param [in] index m_pictのindex。何文字目をレンダリングするか
      //! @param [in] pen_x この文字のm_image上の描画開始位置
      //! @param [in] maxtop 全ての文字の中の高さの最大値
      //! @return なし
      void draw_single_character(const int index, const int pen_x, const int maxtop) {
    
        char* buffer = &m_pict[index].m_pic[0];
        int Width = m_pict[index].width;
        int Height = m_pict[index].height;
        int startx = pen_x + m_pict[index].left;
        int starty = -m_pict[index].top + maxtop;
    
        for (size_t y = 0; y < Height; y++) {
          for (size_t x = 0; x < Width; x++) {
    
            int xx = startx + x;
            int yy = starty + y;
    
            if (xx < 0)continue;
            if (yy < 0)continue;
            if (xx >= imageWidth)continue;
            if (yy >= imageHeight)continue;
    
            if (buffer[y * Width + x]) {
              m_image[pixel_pos(xx, yy)] = buffer[y * Width + x];
            }
          }
        }
    
      }
      //! @brief 全ての文字を結果に書き込む
      //! @param [in] maxtop 全ての文字の中の高さの最大値
      //! @return なし
      void characters_to_image(const int maxtop) {
    
        int pen_x = 0;
    
        for (size_t i = 0; i < m_pict.size(); i++) {
          if (m_pict[i].m_pic.size()) {
            // 画像書き込み
            draw_single_character(i, pen_x,maxtop);
          }
    
          // 描画位置を更新
          pen_x += m_pict[i].advancex;
        }
    
      }
    public:
    
      //! @brief コンストラクタ
      //! @param [in] ftLib FreeTypeライブラリオブジェクトへのポインタ
      //! @param [in] fontfilename フォントファイル名
      SingleLineText(FT_Library* ftLib,const char* fontfilename) {
        m_plib = ftLib;
    
        FT_Error error;
    
        // フォントファイル読み込み
        error = FT_New_Face(
          *m_plib,
          fontfilename,
          0,
          &face
        );
    
        //文字コード指定
        error = FT_Select_Charmap(
          face,               // target face object
          FT_ENCODING_UNICODE // エンコード指定
        );
    
    
        if (error == FT_Err_Unknown_File_Format) {
          throw "FT_Err_Unknown_File_Format";
        }
        else if (error) {
          throw "FT_Err";
        }
    
      }
      //! @brief ラスタライズ
      //! @param [in] text 元のテキスト
      //! @param [in] pixel_size_y 文字サイズ
      //! @return なし
      void rasterize(std::wstring text,const int pixel_size_y) {
    
        FT_Error error;
    
        error = FT_Set_Pixel_Sizes(
          face,            // handle to face object
          0,               // pixel_width
          pixel_size_y);   // pixel_height
    
        int maxtop = INT_MIN;
        imageHeight = INT_MIN;
        imageWidth = 0;
    
        m_pict.clear();
    
        //textの各文字について画像を作成
        for (size_t k = 0; k < text.size(); k++) {
    
          // 文字の取得
          FT_ULong character = text[k];
          FT_UInt char_index = FT_Get_Char_Index(face, character);
    
          // グリフ(字の形状)読込
          //FT_LOAD_COLOR
          error = FT_Load_Glyph(face, char_index, FT_LOAD_RENDER | FT_LOAD_COLOR);
          if (error)
            return; // ignore errors
    
          // 文字を画像化
          //FT_RENDER_MODE_MONO
          //FT_RENDER_MODE_NORMAL
          FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
    
          //データを8bit画像にする
          FT_Bitmap tmpbmp;
          FT_Bitmap_Init(&tmpbmp);
          FT_Bitmap_Convert(*m_plib, &face->glyph->bitmap, &tmpbmp, 1);
    
          m_pict.emplace_back();
    
          ////////////////////////////////////////
          //画像を配列に保存
          const int Width = tmpbmp.width;
          const int Height = tmpbmp.rows;
          for (size_t y = 0; y < Height; y++) {
            for (size_t x = 0; x < Width; x++) {
    
              m_pict.back().m_pic.push_back(tmpbmp.buffer[y * Width + x]);
    
            }
          }
    
          FT_Bitmap_Done(*m_plib, &tmpbmp);
    
    
          m_pict.back().width = Width;
          m_pict.back().height = Height;
          m_pict.back().left = face->glyph->bitmap_left;
          m_pict.back().top = face->glyph->bitmap_top;
          m_pict.back().advancex = face->glyph->advance.x >> 6;
          m_pict.back().advancey = face->glyph->advance.y >> 6;
          ////////////////////////////////////////
    
          maxtop = (std::max)(maxtop, m_pict.back().top);
    
          imageHeight = (std::max)(
            imageHeight, 
            -m_pict[k].top + maxtop + m_pict[k].height
            );
          imageWidth += m_pict.back().advancex;
    
        }
    
        //結果画像のメモリ確保
        m_image.resize(imageWidth * imageHeight, 0);
    
        //画像に全ての文字を書き込む
        characters_to_image(maxtop);
    
      }
      void done_face() {
        FT_Done_Face(face);
      }
      int ImageWidth() { return imageWidth; }
      int ImageHeight() { return imageHeight; }
      const unsigned char* image()const { return &m_image[0]; }
    
    
    };
    

    呼び出し

    #include <string>
    #include <array>
    
    #include "SingleLineText.hpp"
    
    #include "pnm_rw.hpp"
    
    #pragma warning(disable:4996)
    
    #pragma comment(lib,"freetyped.lib")
    
    
    int main()
    {
      FT_Library  library; // handle to library
      FT_Error error;
    
    
      error = FT_Init_FreeType(&library);
      if (error)
        return -1;
    
      ////msgothic.ttc
      //meiryo
      SingleLineText slt(&library, "C:\\Windows\\Fonts\\msgothic.ttc");
    
      int pixel_size_y = 24;
    
      std::wstring chars = L"いろ は。にほへと,abc d";
      
      slt.rasterize(chars, pixel_size_y);//画像の作成
    
      //ファイル出力
      write_pnm(
        "C:\\test\\text.pgm", 
        slt.image(),
        slt.ImageWidth(), 
        slt.ImageHeight(), 
        PNM_TYPE::P2
      );
    
    
      slt.done_face();
      // FreeType2の解放
      FT_Done_FreeType(library);
    }