美文网首页
cImg库绘制自定义字体

cImg库绘制自定义字体

作者: 何亮hook_8285 | 来源:发表于2022-10-29 01:19 被阅读0次

    简介

    cImg是C++图像处理库,在使用cimg库时发现绘制文本不太友好,不能指定自定义字体,所以本文提供的代码能让cimg库绘制TTF字体。

    计算机显示文字过程

    • 给定一个文字'A':0x41,"中":可能有GBK、unicode 等编码,可以确定它的编码值

    • 根据编码值从字体文件中找到"glyph"字形 ,(由于字体文件可以是GBK、unicode等,在字库文件前还存有字符映射表charmaps,支持多种编码)

    • 设置字体大小

    • 用某些函数把"glyph"字形里的点缩放设置的大小

    • 转换为位图点阵

    • 在LCD等显示器中显示出来

    CImg库绘制自定义字体

    以下代码使用到freetype库加载指定的ttf字体文件,将字符转位图、并且输出cimg图像中。

    
    #define cimg_use_png
    #define cimg_use_jpeg
    #define cimg_use_tiff
    #include <CImg.h>
    #include <freetype/freetype.h>
    
    
    /// 初始化freetype结构体
    /// \param ftlib 字体库
    /// \param face 字体内容
    /// \param fontFullName ttf字体路径
    void initFreetype( FT_Library& ftlib,FT_Face& face,const std::string& fontFullName){
        FT_Error fterr;
        if((fterr = FT_Init_FreeType( &ftlib ))) {
            throw "初始化FT_Library库失败";
        }
    
        if((fterr = FT_New_Face(ftlib, fontFullName.c_str(), 0, &face))){
            if(fterr == FT_Err_Unknown_File_Format) {
                throw "未找到ttf字体文件";
            } else {
                throw "初始化FT_Face失败";
            }
    
        }
    
    }
    
    /**
     * 绘制每一个字体
     * @param glyphSlot 字形数据
     * @param image  绘制图片
     * @param shiftX  绘制x坐标
     * @param shiftY  绘制y坐标
     * @param fontColor 字体颜色
     */
    void drawGlyph(FT_GlyphSlot& glyphSlot,cimg_library::CImg<unsigned char>& image,const int& shiftX,const int& shiftY,unsigned char fontColor[] = NULL){
        unsigned char buff[] = {255, 255, 255};
        if (fontColor == NULL){
            fontColor = buff;
        }
    
        float alpha = 0;
        for (int y = 0; y < glyphSlot->bitmap.rows; ++y){
            for (int x = 0; x < glyphSlot->bitmap.width; ++x){
                unsigned char glyphValue = glyphSlot->bitmap.buffer[y * glyphSlot->bitmap.width + x];
                alpha = (255.0f - glyphValue) / 255.0f;
                cimg_forC(image, c){
                    unsigned char value = (float) glyphValue*fontColor[c]/(255.0f);
                    image(x + shiftX, y + shiftY, c) =alpha * image(x + shiftX, y + shiftY, c) + (1.0 - alpha) * value;
                }
            }
        }
    
    }
    
    /**
     *
     * @param face 字体对象
     * @param image 绘制图片
     * @param heightText 字体高度
     * @param text  绘制文字
     * @param leftTopX  x坐标
     * @param leftTopY y坐标
     * @param fontColor 字体颜色
     * @param separateGlyphWidth 每一个文字间隔,默认1
     */
    void drawText(FT_Face& face,cimg_library::CImg<unsigned char>& image,const int& heightText,const std::wstring& text,const int& leftTopX,const int& leftTopY,unsigned char fontColor[] = NULL,int separateGlyphWidth=1){
        FT_Set_Pixel_Sizes(face, 0, heightText);
        FT_GlyphSlot glyphSlot = face->glyph;
        int shiftX = leftTopX;
        int shiftY = 0;
        for(int numberSymbol = 0; numberSymbol < text.length(); ++numberSymbol){
            shiftY = leftTopY;
            bool isSpace = false;
            FT_ULong symbol = text.at(numberSymbol);
            if (symbol == ' ') {
                symbol = 'a';
                isSpace = true;
            }
    
            if(FT_Load_Char(face, symbol, FT_LOAD_RENDER)){
                throw "在字体库加载加载文字失败!! \n";
            }
            float shiftFactor = glyphSlot->bitmap.rows - glyphSlot->bitmap_top;
            shiftY += shiftFactor;
            shiftY +=  (heightText > glyphSlot->bitmap.rows) ? heightText - glyphSlot->bitmap.rows : 0;
            if(!isSpace){
                drawGlyph(glyphSlot, image, shiftX, shiftY, fontColor);
            }
            shiftX += glyphSlot->bitmap.width + separateGlyphWidth;
    
        }
    
    }
    
    /**
     * 销毁FT_Library和FT_Face
     * @param ftlib
     * @param face
     */
    void closeFreetype(FT_Library& ftlib,FT_Face& face){
        FT_Done_Face(face);
        FT_Done_FreeType(ftlib);
    }
    
    
    int main() {
        FT_Library ftlib;
        FT_Face face;
        char *ttfFilename="d:\\simhei.ttf";
        initFreetype(ftlib, face, ttfFilename);
        cimg_library::CImg<unsigned char> img(640, 400, 1, 3);
        img.fill(255);
        unsigned char redFontColor[] = {0, 0, 0};
        drawText(face, img, 15, L"heliang", 0, 0, redFontColor,1);
        img.save_bmp("d:\\imgfont.bmp");
        closeFreetype(ftlib, face);
        return 0;    
    }
    

    相关文章

      网友评论

          本文标题:cImg库绘制自定义字体

          本文链接:https://www.haomeiwen.com/subject/qtrqtdtx.html