忘備録-備忘録

技術的な備忘録

True type fontのレンダリング その4

2020-04-21 21:12:37 | Linux
True type fontをbitmapにレンダリングするプログラムを作成しました。レンダリングにはFreeTypeライブラリを使用しました。プログラムの作成はRaspberry Pi4で行っています。画像の表示にはEGGX / ProCALLライブラリを使用しました。 

前回のプログラムは",pq"などの文字は指定した座標の下にはみ出してしまいます。これを指定の範囲に収めます。
face->size->metrics.descender ベースラインの下にはみ出す長さ
face->size->metrics.height フォントの高さ
face->size->metrics.max_advance フォントの最大幅
これらの値は26.6の固定小数点になっています。

#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <ft2build.h>
#include FT_FREETYPE_H

#include <eggx.h> /* EGGX を使う時に必要 */

int main(int argc,char *argv[]){
    FT_Library library;
    FT_Face    face;
    FT_GlyphSlot slot;
    int error,win;
    char text[] = "hello,world!";
    int pen_x, pen_y;
    int num_chars = (int)strlen( text);

    gsetinitialattributes(DISABLE, BOTTOM_LEFT_ORIGIN); /*eggxの座標設定を通常のグラフィックスと同じに*/
    win = gopen(800,400); /* 800x400 ピクセルのグラフィックス用ウィンドゥを開く */
    //layer(win, 0, 1); /* 描画レイヤを設定 */
    // FreeTypeの初期化とTrueTypeフォントの読み込み
    error = FT_Init_FreeType( &library );
    if(error) {
        fprintf(stderr,"error FT_Init_FreeType\n");
        exit(EXIT_FAILURE);
    }
    error = FT_New_Face( library, "/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc", 0, &face );
    if(error == FT_Err_Unknown_File_Format) {
        fprintf(stderr,"unsupport fonts format\n");
        exit(EXIT_FAILURE);
    } else if(error) {
        fprintf(stderr,"fonts file not found\n");
        exit(EXIT_FAILURE);
    }
    slot = face->glyph;

    error = FT_Set_Pixel_Sizes( face, 0, 120 ); //ピクセル単位でサイズ指定
    //error = FT_Set_Char_Size( face, 0, 16 * 64, 300, 300); //ポイント単位でサイズ指定
    if(error) {
        fprintf(stderr,"FT_Set_Pixel_Sizes\n");
        exit(EXIT_FAILURE);
    }
    pen_x = 10; // 文字の表示座標 左下のベースライン
    pen_y = 150;
    newrgbcolor(win,0,0,255);
    drawline(win,pen_x,pen_y,800,pen_y);
    for (int n = 0;n < num_chars; n++ ){
        int i;
        FT_Bitmap bitmap;

        // n文字目の文字をビットマップ化
        //error = FT_Load_Char( face, text[n], FT_LOAD_VERTICAL_LAYOUT|FT_LOAD_RENDER );//縦書き
        error = FT_Load_Char( face, text[n], FT_LOAD_RENDER );// 横書き
        if(error) {
            fprintf(stderr,"FT_Load_Char error\n");
            exit(EXIT_FAILURE);
        }
        bitmap = slot->bitmap;

        for( i = 0; i < bitmap.rows * bitmap.width; i++){
            newrgbcolor(win,bitmap.buffer[i],bitmap.buffer[i],bitmap.buffer[i]);
            int x = i % bitmap.width+pen_x + slot->bitmap_left;
            int y = i / bitmap.width+pen_y - slot->bitmap_top + (face->size->metrics.descender >>6);
            pset(win,x, y); /* 点を描く */
        }
        pen_x += slot->advance.x >> 6;
        pen_y += slot->advance.y >> 6;

    }
    //copylayer(win, 1, 0);  /* レイヤ1をレイヤ0に瞬時にコピー */
    ggetch(); /* キー入力があるまで待つ */
    gclose(win); /* グラフィックス用ウィンドゥを閉じる */
    error = FT_Done_Face( face );
    if(error) {
        fprintf(stderr,"error FT_Done_Face\n");
        exit(EXIT_FAILURE);
    }
    error = FT_Done_FreeType( library );
    if(error) {
        fprintf(stderr,"error FT_Done_FreeType\n");
        exit(EXIT_FAILURE);
    }
    return 0;
}

実行結果


参考


True type fontのレンダリング その3

2020-04-21 20:51:01 | Linux
True type fontをbitmapにレンダリングするプログラムを作成しました。レンダリングにはFreeTypeライブラリを使用しました。プログラムの作成はRaspberry Pi4で行っています。画像の表示にはEGGX / ProCALLライブラリを使用しました。 

文字の大きさが違うのに同じ位置から表示を始めてしまったために表示がおかしくなっています。文字ごとのbitmapの表示位置は、
slot->bitmap_left
slot->bitmap_top
に保存されます。
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <ft2build.h>
#include FT_FREETYPE_H

#include <eggx.h> /* EGGX を使う時に必要 */

int main(int argc,char *argv[]){
    FT_Library library;
    FT_Face    face;
    FT_GlyphSlot slot;
    int error,win;
    char text[] = "hello,world!";
    int pen_x, pen_y;
    int num_chars = (int)strlen( text);

    gsetinitialattributes(DISABLE, BOTTOM_LEFT_ORIGIN); /*eggxの座標設定を通常のグラフィックスと同じに*/
    win = gopen(800,400); /* 800x400 ピクセルのグラフィックス用ウィンドゥを開く */
    //layer(win, 0, 1); /* 描画レイヤを設定 */
    // FreeTypeの初期化とTrueTypeフォントの読み込み
    error = FT_Init_FreeType( &library );
    if(error) {
        fprintf(stderr,"error FT_Init_FreeType\n");
        exit(EXIT_FAILURE);
    }
    error = FT_New_Face( library, "/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc", 0, &face );
    if(error == FT_Err_Unknown_File_Format) {
        fprintf(stderr,"unsupport fonts format\n");
        exit(EXIT_FAILURE);
    } else if(error) {
        fprintf(stderr,"fonts file not found\n");
        exit(EXIT_FAILURE);
    }
    slot = face->glyph;

    error = FT_Set_Pixel_Sizes( face, 0, 120 ); //ピクセル単位でサイズ指定
    //error = FT_Set_Char_Size( face, 0, 16 * 64, 300, 300); //ポイント単位でサイズ指定
    if(error) {
        fprintf(stderr,"FT_Set_Pixel_Sizes\n");
        exit(EXIT_FAILURE);
    }
    pen_x = 10; // 文字の表示座標 左下のベースライン
    pen_y = 150;
    newrgbcolor(win,0,0,255);
    drawline(win,pen_x,pen_y,800,pen_y);
    for (int n = 0;n < num_chars; n++ ){
        int i;
        FT_Bitmap bitmap;

        // n文字目の文字をビットマップ化
        //error = FT_Load_Char( face, text[n], FT_LOAD_VERTICAL_LAYOUT|FT_LOAD_RENDER );//縦書き
        error = FT_Load_Char( face, text[n], FT_LOAD_RENDER );// 横書き
        if(error) {
            fprintf(stderr,"FT_Load_Char error\n");
            exit(EXIT_FAILURE);
        }
        bitmap = slot->bitmap;

        for( i = 0; i < bitmap.rows * bitmap.width; i++){
            newrgbcolor(win,bitmap.buffer[i],bitmap.buffer[i],bitmap.buffer[i]);
            int x = i % bitmap.width+pen_x + slot->bitmap_left;
            int y = i / bitmap.width+pen_y - slot->bitmap_top;
            pset(win,x, y); /* 点を描く */
        }
        pen_x += slot->advance.x >> 6;
        pen_y += slot->advance.y >> 6;

    }
    //copylayer(win, 1, 0);  /* レイヤ1をレイヤ0に瞬時にコピー */
    ggetch(); /* キー入力があるまで待つ */
    gclose(win); /* グラフィックス用ウィンドゥを閉じる */
    error = FT_Done_Face( face );
    if(error) {
        fprintf(stderr,"error FT_Done_Face\n");
        exit(EXIT_FAILURE);
    }
    error = FT_Done_FreeType( library );
    if(error) {
        fprintf(stderr,"error FT_Done_FreeType\n");
        exit(EXIT_FAILURE);
    }
    return 0;
}

実行結果


正しく表示されました。

参考





True type fontのレンダリング その2

2020-04-21 20:45:25 | Linux
True type fontをbitmapにレンダリングするプログラムを作成しました。レンダリングにはFreeTypeライブラリを使用しました。プログラムの作成はRaspberry Pi4で行っています。画像の表示にはEGGX / ProCALLライブラリを使用しました。

文字の位置を修正します。
次の文字の座標は
slot->advance.x
slot->advance.y
に保存されます。これらの変数は26.6の固定小数点を使用しています。
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <ft2build.h>
#include FT_FREETYPE_H

#include <eggx.h> /* EGGX を使う時に必要 */

int main(int argc,char *argv[]){
    FT_Library library;
    FT_Face    face;
    FT_GlyphSlot slot;
    int error,win;
    char text[] = "hello,world!";
    int pen_x, pen_y;
    int num_chars = (int)strlen( text);

    gsetinitialattributes(DISABLE, BOTTOM_LEFT_ORIGIN); /*eggxの座標設定を通常のグラフィックスと同じに*/
    win = gopen(800,400); /* 800x400 ピクセルのグラフィックス用ウィンドゥを開く */
    //layer(win, 0, 1); /* 描画レイヤを設定 */
    // FreeTypeの初期化とTrueTypeフォントの読み込み
    error = FT_Init_FreeType( &library );
    if(error) {
        fprintf(stderr,"error FT_Init_FreeType\n");
        exit(EXIT_FAILURE);
    }
    error = FT_New_Face( library, "/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc", 0, &face );
    if(error == FT_Err_Unknown_File_Format) {
        fprintf(stderr,"unsupport fonts format\n");
        exit(EXIT_FAILURE);
    } else if(error) {
        fprintf(stderr,"fonts file not found\n");
        exit(EXIT_FAILURE);
    }
    slot = face->glyph;

    error = FT_Set_Pixel_Sizes( face, 0, 120 ); //ピクセル単位でサイズ指定
    //error = FT_Set_Char_Size( face, 0, 16 * 64, 300, 300); //ポイント単位でサイズ指定
    if(error) {
        fprintf(stderr,"FT_Set_Pixel_Sizes\n");
        exit(EXIT_FAILURE);
    }
    pen_x = 10; // 文字の表示座標 左下のベースライン
    pen_y = 150;
    newrgbcolor(win,0,0,255);
    drawline(win,pen_x,pen_y,800,pen_y);
    for (int n = 0;n < num_chars; n++ ){
        int i;
        FT_Bitmap bitmap;

        // n文字目の文字をビットマップ化
        //error = FT_Load_Char( face, text[n], FT_LOAD_VERTICAL_LAYOUT|FT_LOAD_RENDER );//縦書き
        error = FT_Load_Char( face, text[n], FT_LOAD_RENDER );// 横書き
        if(error) {
            fprintf(stderr,"FT_Load_Char error\n");
            exit(EXIT_FAILURE);
        }
        bitmap = slot->bitmap;

        for( i = 0; i < bitmap.rows * bitmap.width; i++){
            newrgbcolor(win,bitmap.buffer[i],bitmap.buffer[i],bitmap.buffer[i]);
            int x = i % bitmap.width+pen_x;
            int y = i / bitmap.width+pen_y;
            pset(win,x, y); /* 点を描く */
        }
        pen_x += slot->advance.x >> 6;
        pen_y += slot->advance.y >> 6;

    }
    //copylayer(win, 1, 0);  /* レイヤ1をレイヤ0に瞬時にコピー */
    ggetch(); /* キー入力があるまで待つ */
    gclose(win); /* グラフィックス用ウィンドゥを閉じる */
    error = FT_Done_Face( face );
    if(error) {
        fprintf(stderr,"error FT_Done_Face\n");
        exit(EXIT_FAILURE);
    }
    error = FT_Done_FreeType( library );
    if(error) {
        fprintf(stderr,"error FT_Done_FreeType\n");
        exit(EXIT_FAILURE);
    }
    return 0;
}

実行結果

位置がおかしい。その3に続きます。

参考

True type fontのレンダリング その1

2020-04-21 20:06:22 | Linux
True type fontをbitmapにレンダリングするプログラムを作成しました。レンダリングにはFreeTypeライブラリを使用しました。プログラムの作成はRaspberry Pi4で行っています。画像の表示にはEGGX / ProCALLライブラリを使用しました。

FreeTypeライブラリのインストール
$ sudo apt install libfreetype6-dev

コンパイル
$ gcc -Wall -o hoge hoge.c -I/usr/include/freetype2 -lfreetype

EGGX/ProCALLも含めた場合
$ gcc -Wall -o hoge hoge.c -I/usr/local/include -I/usr/include/freetype2  -L/usr/local/lib   -leggx -lX11 -lm -lfreetype

基本となるプログラム
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* freetype ライブラリ用のヘッダ */
#include <ft2build.h>
#include FT_FREETYPE_H
/* EGGX / ProCALL  C言語,FORTRAN言語用のX11グラフィックスライブラリ*/
#include <eggx.h> /* EGGX を使う時に必要 */

int main(int argc,char *argv[]){
    FT_Library library;
    FT_Face    face;
    FT_GlyphSlot slot;
    int error,win;
    char text[] = "hello,world!";
    int pen_x, pen_y;
    int num_chars = (int)strlen( text);

    gsetinitialattributes(DISABLE, BOTTOM_LEFT_ORIGIN); /*eggxの座標設定を通常のグラフィックスと同じに*/
    win = gopen(800,400); /* 800x400 ピクセルのグラフィックス用ウィンドゥを開く */
    //layer(win, 0, 1); /* 描画レイヤを設定 */
    /* FreeTypeの初期化 */
    error = FT_Init_FreeType( &library );
    if(error) {
        fprintf(stderr,"error FT_Init_FreeType\n");
        exit(EXIT_FAILURE);
    }
    /* TrueTypeフォントの読み込み */
    /* フォントファイルは fc-list コマンドで取得可能 */
    error = FT_New_Face( library, "/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc", 0, &face );
    if(error == FT_Err_Unknown_File_Format) {
        fprintf(stderr,"unsupport fonts format\n");
        exit(EXIT_FAILURE);
    } else if(error) {
        fprintf(stderr,"fonts file not found\n");
        exit(EXIT_FAILURE);
    }
    slot = face->glyph;

    error = FT_Set_Pixel_Sizes( face, 0, 120 ); /* ピクセル単位でサイズ指定 */
    //error = FT_Set_Char_Size( face, 0, 16 * 64, 300, 300); /* ポイント単位でサイズ指定 */
    if(error) {
        fprintf(stderr,"error FT_Set_Pixel_Sizes\n");
        exit(EXIT_FAILURE);
    }
    pen_x = 10;  /* 文字の表示座標 左下のベースライン x座標 */
    pen_y = 150; /* 文字の表示座標 左下のベースライン y座標 */
    newrgbcolor(win,0,0,255); /* 色の指定 */
    drawline(win,pen_x,pen_y,800,pen_y); /* 文字の基準となる線を引く */
    for (int n = 0;n < num_chars; n++ ){
        int i;
        FT_Bitmap bitmap;

        /* n文字目の文字をビットマップ化 */
        //error = FT_Load_Char( face, text[n], FT_LOAD_VERTICAL_LAYOUT|FT_LOAD_RENDER ); /* 縦書き */
        error = FT_Load_Char( face, text[n], FT_LOAD_RENDER ); /* 横書き */
        if(error) {
            fprintf(stderr,"error FT_Load_Char\n");
            exit(EXIT_FAILURE);
        }
        bitmap = slot->bitmap;
        /* bitmap.buffer[] に保存されているデータはアンチエリアシングのためのα値 */
        /* bitmap.width はbitmap化された文字画像の横幅 */
        /* bitmap.rows はbitmap化された文字画像の高さ */
        for( i = 0; i < bitmap.rows * bitmap.width; i++){
            newrgbcolor(win,bitmap.buffer[i],bitmap.buffer[i],bitmap.buffer[i]);/* 色の指定 */
            int x = i % bitmap.width+pen_x;
            int y = i / bitmap.width+pen_y;
            pset(win,x, y); /* 点を描く */
        }
    }
    //copylayer(win, 1, 0);  /* レイヤ1をレイヤ0に瞬時にコピー */
    ggetch(); /* キー入力があるまで待つ */
    gclose(win); /* グラフィックス用ウィンドゥを閉じる */
    /* フォントデータの終了処理 */
    error = FT_Done_Face( face );
    if(error) {
        fprintf(stderr,"error FT_Done_Face\n");
        exit(EXIT_FAILURE);
    }
    /* FreeTypeの終了処理 */
    error = FT_Done_FreeType( library );
    if(error) {
        fprintf(stderr,"error FT_Done_FreeType\n");
        exit(EXIT_FAILURE);
    }
    return 0;
}

実行結果

文字の位置がずれています。

参考



コンソールターミナルに画像を表示

2020-04-02 23:37:24 | raspberry ...
前回X11を使わずに、コンソールターミナルのみで日本語の表示・入力を行う方法を書きましたが、ついでにコンソールターミナルに画像を表示する方法を解説します。
fbiというソフトがaptからインストールでき有名なようですが、fbtermと同時に使用できません。そこでfbvというソフトを使用します。

インストール
$ git clone https://github.com/godspeed1989/fbv.git
$ cd fbv
$ ./configure
$ make
$ sudo make install

使用方法
$ fbv 画像ファイル名
$ fbv *.jpg

キー入力で操作します。
Input keys:
 r               : Redraw the image
 < or ,        : Previous image
 > or .        : Next image
 a, d, w, x  : Pan the image
 f               : Toggle resizing on/off
 k              : Toggle resizing quality
 e              : Toggle enlarging on/off
 i               : Toggle respecting the image aspect on/off
 n              : Rotate the image 90 degrees left
 m             : Rotate the image 90 degrees right
 p              : Disable all transformations
 q              : Quit



参考