スポンサーリンク

FreeType2を試す-3-小さいサイズで描画

出力用関数

//! @brief PBM(1byte,テキスト)を書き込む
//! @param [in] fname ファイル名
//! @param [in] width 画像の幅
//! @param [in] height 画像の高さ
//! @param [in] p 画像のメモリへのアドレス
//! @details 1画素1Byteのメモリを渡すと、0,1テキストでファイル名fnameで書き込む
void pbmP1_Write(const char* const fname, const int width, const int height, const unsigned char* const p) { // PPM ASCII

  FILE* fp = fopen(fname, "wb");
  fprintf(fp, "P1\n%d\n%d\n", width, height);

  size_t k = 0;
  for (size_t i = 0; i < (size_t)height; i++) {
    for (size_t j = 0; j < (size_t)width; j++) {
      fprintf(fp, "%d ", p[k] ? 0 : 1);
      k++;
    }
    fprintf(fp, "\n");
  }

  fclose(fp);
}

この時、以下のコードで、以下のpixel_heightで出力すると、正常に出力されない。文字サイズが小さすぎると結果が壊れる。

失敗例

#include <ft2build.h>
#include FT_FREETYPE_H


#pragma warning(disable:4996)

#pragma comment(lib,"freetype.lib")


int main()
{

  FT_Library  library; // handle to library
  FT_Error error;

  error = FT_Init_FreeType(&library);
  if (error)
    return -1;

  FT_Face face;      // handle to face object

  //msgothic.ttc
  //meiryo.ttc
  // フォントファイル読み込み
  error = FT_New_Face(
    library,
    "C:\\Windows\\Fonts\\msgothic.ttc",
    0,
    &face
  );

  //文字コード指定
  error = FT_Select_Charmap(
    face,               // target face object
    FT_ENCODING_UNICODE // エンコード指定
  );


  if (error == FT_Err_Unknown_File_Format)
    return -1;
  else if (error)
    return -1;
  int pixel_heigth =16;
  //この二つの値でフォントサイズ調整
  FT_Set_Pixel_Sizes(
    face,          // handle to face object
    0,             // pixel_width  
    pixel_heigth   // pixel_height
  );

    // 文字の取得
  FT_ULong character = wchar_t(L'あ');
  FT_UInt char_index = FT_Get_Char_Index(face, character);

  // グリフ(字の形状)読込
  error = FT_Load_Glyph(face, char_index, FT_LOAD_RENDER);
  if (error)
    return -1; // ignore errors

    // 文字を画像化
  FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);


  FT_Bitmap& glyphbitmap = face->glyph->bitmap;



  int Width = glyphbitmap.width;
  int Height = glyphbitmap.rows;
  pbmP1_Write(// ファイル保存
    "C:\\test\\freetypetest.pbm",
    Width,
    Height,
    glyphbitmap.buffer
  );

  // FreeType2の解放
  FT_Done_Face(face);
  FT_Done_FreeType(library);
}

これは(多分)、フォントサイズが小さいときはビットマップフォントが使われ、pixel_typeが変わってしまっているから。

FT_Bitmap_Convertで画像データを変換すれば、取り出したフォントの形式にかかわらず、8bppにできる。

  FT_Bitmap glyphbitmap;// 新しい画像データ
  FT_Bitmap_Init(&glyphbitmap);// 新しい画像データの初期化
  FT_Bitmap_Convert(library, &face->glyph->bitmap, &glyphbitmap, 1);// 文字画像を8bppに変換

  int Width = glyphbitmap.width;
  int Height = glyphbitmap.rows;
  pgmP2_Write(// ファイル保存
    "C:\\test\\freetypetest.pbm",
    Width,
    Height,
    255,
    glyphbitmap.buffer
  );

  FT_Bitmap_Done(library, &glyphbitmap);// 文字画像を解放

成功例

int main()
{

  FT_Library  library; // handle to library
  FT_Error error;

  error = FT_Init_FreeType(&library);
  if (error)
    return -1;

  FT_Face face;      // handle to face object

  //msgothic.ttc
  //meiryo.ttc
  // フォントファイル読み込み
  error = FT_New_Face(
    library,
    "C:\\Windows\\Fonts\\msgothic.ttc",
    0,
    &face
  );

  //文字コード指定
  error = FT_Select_Charmap(
    face,               // target face object
    FT_ENCODING_UNICODE // エンコード指定
  );


  if (error == FT_Err_Unknown_File_Format)
    return -1;
  else if (error)
    return -1;

  int pixel_heigth = 16;

  //この二つの値でフォントサイズ調整
  FT_Set_Pixel_Sizes(
    face,          // handle to face object
    0,             // pixel_width  
    pixel_heigth   // pixel_height
  );

  // 文字の取得
  FT_ULong character = wchar_t(L'あ');
  FT_UInt char_index = FT_Get_Char_Index(face, character);

  // グリフ(字の形状)読込
  error = FT_Load_Glyph(face, char_index, FT_LOAD_RENDER | FT_LOAD_COLOR);
  if (error)
    return -1; // ignore errors

    // 文字を画像化
  FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);


  FT_Bitmap glyphbitmap;
  FT_Bitmap_Init(&glyphbitmap);
  FT_Bitmap_Convert(library, &face->glyph->bitmap, &glyphbitmap, 1);

  int Width = glyphbitmap.width;
  int Height = glyphbitmap.rows;
  pgmP2_Write(// ファイル保存
    "C:\\test\\freetypetest.pbm",
    Width,
    Height,
    255,
    glyphbitmap.buffer
  );

  FT_Bitmap_Done(library, &glyphbitmap);
  // FreeType2の解放
  FT_Done_Face(face);
  FT_Done_FreeType(library);
}

pixel_mode

フォントサイズによってpixel_modeが違うことがある。以下のコードで確認する。

  switch (face->glyph->bitmap.pixel_mode) {
  case FT_PIXEL_MODE_NONE:
    printf("FT_PIXEL_MODE_NONE");
    break;
  case FT_PIXEL_MODE_MONO:
    printf("FT_PIXEL_MODE_MONO");
    break;
  case FT_PIXEL_MODE_GRAY:
    printf("FT_PIXEL_MODE_GRAY");
    break;
  case FT_PIXEL_MODE_GRAY2:
    printf("FT_PIXEL_MODE_GRAY2");
    break;
  case FT_PIXEL_MODE_GRAY4:
    printf("FT_PIXEL_MODE_GRAY4");
    break;
  case FT_PIXEL_MODE_LCD:
    printf("FT_PIXEL_MODE_LCD");
    break;
  case FT_PIXEL_MODE_LCD_V:
    printf("FT_PIXEL_MODE_LCD_V");
    break;
  case FT_PIXEL_MODE_BGRA:
    printf("FT_PIXEL_MODE_BGRA");
    break;
  }
  getchar();
pixel heightpixel_mode
16FT_PIXEL_MODE_MONO
32FT_PIXEL_MODE_GRAY

コメントを残す

メールアドレスが公開されることはありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: