简介
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;
}
网友评论