基于FreeType2实现跨平台的字幕叠加的类

这个类实现了把一个字符串转成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;
}

你可能感兴趣的:(基于FreeType2实现跨平台的字幕叠加的类)