这个类实现了把一个字符串转成RGB点阵,RGB转YUV,和把RGB点阵保存成BMP文件。点阵数据可以直接往其他背景上叠加。
TextToImageFT::TextToImageFT(void)
{
m_rgb24Buff = NULL;
m_yuvBuff = NULL;
expanded_data = NULL;
}
TextToImageFT::~TextToImageFT(void)
{
if(m_rgb24Buff)
free(m_rgb24Buff);
m_rgb24Buff = NULL;
if(m_yuvBuff)
free(m_yuvBuff);
m_yuvBuff = NULL;
if(expanded_data)
free(expanded_data);
expanded_data = NULL;
}
int TextToImageFT::InitFT(const char * fname, unsigned int nHeight)
{
ftHeiht = nHeight;
//初始化FreeType库..
if (FT_Init_FreeType( &ftLibrary ))
{
printf("FT_Init_FreeType failed");
return -1;
}
//加载一个字体,取默认的Face,一般为Regualer
if (FT_New_Face( ftLibrary, fname, 0, &ftFace))
{
printf("FT_New_Face failed (there is probably a problem with your font file)");
return -1;
}
//大小要乘64.这是规定。照做就可以了。
FT_Set_Char_Size(ftFace,ftHeiht << 6, ftHeiht << 6, 96, 96);
#if 0
FT_Matrix matrix;
FT_Vector pen;
//给它设置个旋转矩阵
float angle = (float) -0/180.* 3.14;
matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L );
matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L );
matrix.yx = (FT_Fixed)( sin( angle ) * 0x10000L );
matrix.yy = (FT_Fixed)( cos( angle ) * 0x10000L );
FT_Set_Transform( ftFace, &matrix, &pen );
#endif
return 0;
}
int TextToImageFT::FreeFT()
{
FT_Done_Face(ftFace);
FT_Done_FreeType(ftLibrary);
return 0;
}
int TextToImageFT::PasteImage(int xOffset,int yOffset,int pitch,int width,int height,unsigned char * buff)
{
if(expanded_data)
free(expanded_data);
expanded_data = new unsigned char[ 3 * pitch * height];
memset(expanded_data, 0x00, 3 * pitch * height);
for(int j=0; j < height ; j++)
{
for(int i=0; i < width; i++)
{
// expanded_data[3*(i+(height-j-1)*pitch)]=
// expanded_data[3*(i+(height-j-1)*pitch)+1] =
// expanded_data[3*(i+(height-j-1)*pitch)+2] = buff[i + width*j];
expanded_data[3*(i+j*pitch)]=
expanded_data[3*(i+j*pitch)+1] =
expanded_data[3*(i+j*pitch)+2] = buff[i + width*j];
//(i>=bitmap.width || j>=bitmap.rows) ? 0 : bitmap.buffer[i + bitmap.width*j];
}
}
for (int j = yOffset;j<height;j++)
{
memcpy(m_rgb24Buff+(nWidth*(j+(nHeight-height)/2)+xOffset)*3,expanded_data+pitch*j*3,pitch*3);
}
return 0;
}
int TextToImageFT::CalcTextImageSize(int *width,int *height,const wchar_t * text)
{
int use_kerning;
int pen_x, pen_y;
int start_x, end_x;
int chr;
FT_UInt prev_index;
nWidth = 0;
nHeight = 0;
start_x = 0;
end_x = 0;
pen_x = 0;
pen_y = 0;
use_kerning = FT_HAS_KERNING(ftFace);
prev_index = 0;
for (chr = 0; text[chr];chr++)
{
FT_UInt index;
index = FT_Get_Char_Index(ftFace, text[chr]);
if(FT_Load_Glyph(ftFace,index, FT_LOAD_NO_BITMAP))
printf("FT_Load_Glyph failed");
FT_Glyph glyph;
if(FT_Get_Glyph(ftFace->glyph, &glyph ))
printf("FT_Get_Glyph failed");
FT_Render_Glyph(ftFace->glyph, FT_RENDER_MODE_NORMAL );
FT_Glyph_To_Bitmap( &glyph, ft_render_mode_normal, 0, 1 );
FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph;
//取道位图数据
FT_Bitmap& bitmap=bitmap_glyph->bitmap;
int pitch = bitmap.pitch + 4 -1;
pitch -= pitch%4;
nWidth += pitch;
if(nHeight<bitmap.rows)
nHeight = bitmap.rows;
// free glyph
FT_Done_Glyph(glyph);
glyph = NULL;
}
if(nHeight%2)
nHeight++;
if (width)
*width = nWidth;
if (height)
*height = nHeight;
return 0;
}
int TextToImageFT::DrawText(const wchar_t * text)
{
int width = 0;
int height =0;
int xOffset = 0;
CalcTextImageSize(&width,&height,text);
if(m_rgb24Buff)
{
free(m_rgb24Buff);
m_rgb24Buff = NULL;
}
m_rgb24Buff = (unsigned char*)malloc(nWidth*nHeight*3);
memset(m_rgb24Buff,0,nWidth*nHeight*3);
for (int chr = 0; text[chr];chr++)
{
FT_UInt index;
index = FT_Get_Char_Index(ftFace, text[chr]);
if(FT_Load_Glyph(ftFace,index, FT_LOAD_DEFAULT))
printf("FT_Load_Glyph failed");
FT_Glyph glyph;
if(FT_Get_Glyph(ftFace->glyph, &glyph ))
printf("FT_Get_Glyph failed");
FT_Render_Glyph(ftFace->glyph, FT_RENDER_MODE_NORMAL );
FT_Glyph_To_Bitmap(&glyph, ft_render_mode_normal, 0, 1 );
FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph;
//取道位图数据
FT_Bitmap& bitmap=bitmap_glyph->bitmap;
int pitch = bitmap.pitch + 4 -1;
pitch -= pitch%4;
PasteImage(xOffset,0,pitch,bitmap.width,bitmap.rows,bitmap.buffer);
xOffset+=(pitch);
// free glyph
FT_Done_Glyph(glyph);
glyph = NULL;
}
return 0;
}
int TextToImageFT::GetRGBImage(int *width,int *height,unsigned char ** rgbBuff)
{
*width = nWidth;
*height = nHeight;
*rgbBuff = m_rgb24Buff;
return 0;
}
int TextToImageFT::GetYUV420Image(int *width,int *height,unsigned char ** yuvBuff)
{
if(m_yuvBuff)
{
free(m_yuvBuff);
m_yuvBuff = NULL;
}
m_yuvBuff = NULL;
*width =nWidth;
*height=nHeight;
m_yuvBuff =(unsigned char*) malloc(nWidth*nHeight*3/2);
rgb24_to_yuv420p(m_yuvBuff,m_yuvBuff+nWidth*nHeight,m_yuvBuff+nWidth*nHeight*5/4,m_rgb24Buff,nWidth,nHeight);
*yuvBuff = m_yuvBuff;
return 0;
}
int TextToImageFT::SaveRGBToBMPFile(unsigned char *image, int xsize, int ysize, char *filename)
{
unsigned char header[54] =
{
0x42, 0x4d, 0, 0, 0, 0, 0, 0, 0, 0,
54, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 24, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0
};
long file_size = (long)xsize * (long)ysize * 3 + 54;
header[2] = (unsigned char)(file_size &0x000000ff);
header[3] = (file_size >> 8) & 0x000000ff;
header[4] = (file_size >> 16) & 0x000000ff;
header[5] = (file_size >> 24) & 0x000000ff;
long width = xsize;
header[18] = width & 0x000000ff;
header[19] = (width >> 8) &0x000000ff;
header[20] = (width >> 16) &0x000000ff;
header[21] = (width >> 24) &0x000000ff;
long height = -ysize; //数据倒着填充的
header[22] = height &0x000000ff;
header[23] = (height >> 24) &0x000000ff;
header[24] = (height >> 16) &0x000000ff;
header[25] = (height >> 8) &0x000000ff;
char fname_bmp[128];
sprintf(fname_bmp, "%s.bmp", filename);
FILE *fp;
if (!(fp = fopen(fname_bmp, "wb")))
return -1;
fwrite(header, sizeof(unsigned char), 54, fp);
fwrite(image, sizeof(unsigned char), (size_t)(long)xsize * ysize * 3, fp);
fclose(fp);
return 0;
}