歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Linux下利用FreeType2的API實現字符的顯示

Linux下利用FreeType2的API實現字符的顯示

日期:2017/3/1 10:38:08   编辑:Linux編程

網上的FreeType2例子太少,能顯示漢字的比較難找,C語言代碼寫的更難找,能找到的,基本上是被轉載了N遍的同一個示例代碼,基本上解決不了我的問題。

於是乎,花費了不少時間才完成了這些代碼;

主要功能是:

將傳入的GB2312編碼的char型字符串轉換成圖片數組並輸出。

主要原理是:

將GB2312編碼的char型字符串,轉換成unicode編碼的wchar_t型字符串;

之後,利用FreeType2的API獲取漢字的字體位圖。

代碼看似不怎麼復雜,之前找char轉wchar_t的代碼,沒找到一個合適的,最後呢,東拼西湊,就得到了想要的代碼;

還有,輸出的是記錄每個像素點的256級灰度的數組,也就是和png圖片中alpha通道一樣,0 - 255表示透明度, 0為完全透明,255為不透明;

想要將這些文字貼到圖片上,有個公式:

r2 = (r1 * alpha + r2 * (255 - alpha)) /255;
g2 = (g1 * alpha + g2 * (255 - alpha)) /255;
b2 = (b1 * alpha + b2 * (255 - alpha)) /255;

r、g、b表示圖片的red、green、blue三種顏色,這三種顏色通過組合可以變成不同的顏色;

alpha是文字位圖的alpha通道;

r2、b2、g2是圖片重疊後該像素點顯示的顏色;
r1、b1、g1是文字位圖的每個像素點顯示的顏色。

相關信息請參考這篇文章:http://www.linuxidc.com/Linux/2012-01/52144.htm

有需要這些代碼的人的話,請把代碼改一下,因為這是從我的LCUI圖形庫的代碼中復制過來的,不能直接使用。

[cpp]
  1. #include "LCUI_Build.h"
  2. #include LCUI_MAIN_H
  3. #include LCUI_FONTS_H
  4. #include "all.h"
  5. /*代碼轉換:從一種編碼轉為另一種編碼*/
  6. int code_convert(char *from_charset,char *to_charset,const char *inbuf,unsigned int inlen,
  7. unsigned char *outbuf,unsigned int outlen)
  8. {
  9. iconv_t cd;
  10. const char **pin = &inbuf;
  11. unsigned char **pout = &outbuf;
  12. cd = iconv_open(to_charset,from_charset);
  13. if (cd==0) return -1;
  14. memset(outbuf,0,outlen);
  15. if (iconv(cd,(char**)pin,&inlen,(char**)pout,&outlen)==-1) return -1;
  16. iconv_close(cd);
  17. return 0;
  18. }
  19. /*GB2312碼轉為utf-8碼*/
  20. int GB2312_To_UTF8(const char *inbuf,unsigned int inlen,unsigned char *outbuf,unsigned int outlen)
  21. {
  22. return code_convert("gb2312","utf-8",inbuf,inlen,outbuf,outlen);
  23. }
  24. unsigned short Get_Unicode(char *in_gb2312)
  25. {
  26. unsigned char out[256];
  27. int rc;
  28. unsigned int length_gb2312;
  29. /* gb2312碼轉為utf8碼 */
  30. length_gb2312 = strlen(in_gb2312);
  31. rc = GB2312_To_UTF8(in_gb2312,length_gb2312,out,256);
  32. /* utf8轉unicode碼 */
  33. unsigned short unicode;
  34. unicode = out[0];
  35. if (unicode >= 0xF0) {
  36. unicode = (unsigned short) (out[0] & 0x07) << 18;
  37. unicode |= (unsigned short) (out[1] & 0x3F) << 12;
  38. unicode |= (unsigned short) (out[2] & 0x3F) << 6;
  39. unicode |= (unsigned short) (out[3] & 0x3F);
  40. } else if (unicode >= 0xE0) {
  41. unicode = (unsigned short) (out[0] & 0x0F) << 12;
  42. unicode |= (unsigned short) (out[1] & 0x3F) << 6;
  43. unicode |= (unsigned short) (out[2] & 0x3F);
  44. } else if (unicode >= 0xC0) {
  45. unicode = (unsigned short) (out[0] & 0x1F) << 6;
  46. unicode |= (unsigned short) (out[1] & 0x3F);
  47. }
  48. return unicode;
  49. }
  50. int Show_Font_Bitmap(Font_Bitmap_Data *in_fonts)
  51. /* 功能:在屏幕上以0和1表示字體位圖 */
  52. {
  53. int x,y;
  54. for(y=0;y<in_fonts->height;++y){
  55. for(x=0;x<in_fonts->width;++x){
  56. if(in_fonts->text_alpha[y*in_fonts->width+x]>0)
  57. printf("1");
  58. else printf("0");
  59. }
  60. printf("\n");
  61. }
  62. printf("\n");
  63. return 0;
  64. }
  65. int Get_Fonts_Bitmap(
  66. char *font_file, /* 字體文件路徑 */
  67. char *in_text, /* 輸入的字符串 */
  68. int fonts_pixel_size, /* 字體大小 */
  69. int space, /* 間距 */
  70. Font_Bitmap_Data *out_fonts /* 輸出的位圖數據,Pic_Data是結構體 */
  71. )
  72. /* ****************************************** */
  73. /* 根據傳入的字體庫路徑、字符串、字體尺寸,輸 */
  74. /* 出該字符串的位圖數組 */
  75. /* 本函數使用了freetype2的API */
  76. /* ****************************************** */
  77. {
  78. FT_Library p_FT_Lib = NULL; /* 庫的句柄 */
  79. FT_Face p_FT_Face = NULL; /* face對象的句柄 */
  80. FT_Error error = 0;
  81. FT_Bitmap bitmap;
  82. FT_BitmapGlyph bitmap_glyph;
  83. FT_Glyph glyph;
  84. FT_GlyphSlot slot;
  85. int i , j ,temp,num,bg_height;
  86. char error_str[200];
  87. error = FT_Init_FreeType( & p_FT_Lib); /* 初始化FreeType庫 */
  88. if (error) /* 當初始化庫時發生了一個錯誤 */
  89. {
  90. p_FT_Lib = 0 ;
  91. printf(FT_INIT_ERROR);
  92. return - 1 ;
  93. }
  94. /* 從字體庫文件中獲取字體 */
  95. error = FT_New_Face(p_FT_Lib, font_file , 0 , & p_FT_Face);
  96. if ( error == FT_Err_Unknown_File_Format )
  97. {
  98. printf(FT_UNKNOWN_FILE_FORMAT); /* 未知文件格式 */
  99. return - 1 ;
  100. }
  101. else if (error)
  102. {
  103. printf(FT_OPEN_FILE_ERROR);/* 打開錯誤 */
  104. perror("FreeeType2");
  105. return - 1 ;
  106. }
  107. j = 0;
  108. wchar_t *unicode_text;/* 用於存儲unicode字符 */
  109. char ch[256];
  110. unicode_text = (wchar_t*)calloc(1,sizeof(wchar_t)*(strlen(in_text)*2));/* 申請內存 */
  111. for(i=0;i<strlen(in_text);++i){
  112. memset(ch,0,sizeof(ch)); /* 所有元素置零 */
  113. ch[0] = in_text[i]; /* 獲取in_text中的第i個元素 */
  114. if(ch[0] < 0) {
  115. /* GB2312編碼的漢字,每byte是負數,因此,可以用來判斷是否有漢字 */
  116. if(i < strlen(in_text)-1){/* 如果沒有到字符串末尾 */
  117. ch[1] = in_text[i+1];
  118. ++i;
  119. }
  120. else break;
  121. }
  122. unicode_text[j] = Get_Unicode(ch); /* 開始轉換編碼 */
  123. ++j;
  124. }
  125. num = j; /* 記錄字符的數量 */
  126. int start_x = 0,start_y = 0;
  127. int ch_height = 0,ch_width = 0;
  128. int k,text_width = 0;
  129. size_t size = 0;
  130. unsigned char **text_alpha;
  131. bg_height = fonts_pixel_size+5; /* 背景圖形的高度,這個高度要大於字體的高度,所以是+5 */
  132. /* 分配內存,用於存儲字體背景圖的數據 */
  133. text_alpha = (unsigned char**)malloc(sizeof(unsigned char*)*bg_height);
  134. for(i=0;i<bg_height;++i){
  135. /* 預先為背景圖的每一行分配內存 */
  136. text_alpha[i] = (unsigned char*)malloc(sizeof(unsigned char)*1);
  137. }
  138. FT_Select_Charmap(p_FT_Face,FT_ENCODING_UNICODE); /* 設定為UNICODE,默認的也是 */
  139. FT_Set_Pixel_Sizes(p_FT_Face,0,fonts_pixel_size); /* 設定字體大小 */
  140. slot = p_FT_Face->glyph;
  141. for(temp=0;temp<num;++temp){
  142. /* 開始遍歷unicode編碼的字符串中的每個元素 */
  143. /* 這個函數只是簡單地調用FT_Get_Char_Index和FT_Load_Glyph */
  144. error = FT_Load_Char( p_FT_Face, unicode_text[temp], FT_LOAD_RENDER | FT_LOAD_NO_AUTOHINT);
  145. if(!error){
  146. /* 從插槽中提取一個字形圖像 */
  147. /* 請注意,創建的FT_Glyph對象必須與FT_Done_Glyph成對使用 */
  148. error = FT_Get_Glyph(p_FT_Face -> glyph, &glyph);
  149. if (!error)
  150. {
  151. if(unicode_text[temp] == ' ') {
  152. /* 如果有空格 */
  153. k = 0;
  154. ch_width = (fonts_pixel_size -2)/2;
  155. ch_height = fonts_pixel_size;
  156. text_width = start_x + ch_width;
  157. start_y = 0;
  158. for(i=0;i<bg_height;++i){
  159. text_alpha[i] = (unsigned char*)realloc(text_alpha[i],sizeof(unsigned char)*text_width);
  160. for(j=start_x-space;j<text_width;++j) text_alpha[i][j] = 0;
  161. }
  162. for ( i = 0 ; i < ch_height; ++i)
  163. {
  164. for ( j = 0 ; j < ch_width; ++j)
  165. {
  166. text_alpha[start_y + i][start_x + j] = 0;
  167. ++k;
  168. }
  169. }
  170. start_x += (ch_width+space); /* 畫筆向右邊移動 */
  171. }
  172. else{
  173. /* 256級灰度字形轉換成位圖 */
  174. FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0 ,1);
  175. /* FT_RENDER_MODE_NORMAL 這是默認渲染模式,它對應於8位抗鋸齒位圖。 */
  176. bitmap_glyph = (FT_BitmapGlyph)glyph;
  177. bitmap = bitmap_glyph -> bitmap;
  178. k = 0;
  179. start_y = fonts_pixel_size - slot->bitmap_top + 2; /* 獲取起點的y軸坐標 */
  180. if(start_y < 0) start_y = 0;
  181. if(bitmap.rows > bg_height) ch_height = fonts_pixel_size;
  182. else ch_height = bitmap.rows;
  183. if(ch_height+start_y > bg_height) ch_height = bg_height - start_y;
  184. ch_width = bitmap.width;
  185. text_width = start_x + bitmap.width;
  186. for(i=0;i<bg_height;++i){
  187. /* 動態擴增存儲字體位圖的背景圖形占用的空間 */
  188. text_alpha[i] = (unsigned char*)realloc(text_alpha[i],sizeof(unsigned char)*text_width);
  189. for(j=start_x-space;j<text_width;++j) text_alpha[i][j] = 0;/* 多出來的空間全部置零 */
  190. }
  191. /* 開始將字體位圖貼到背景圖形中 */
  192. for(i = 0; i < bg_height; ++i){
  193. for(j = 0;j < ch_width; ++j){
  194. if(i >= start_y && i < start_y + ch_height){
  195. /* 如果在字體位圖的范圍內 */
  196. text_alpha[i][start_x + j] = bitmap.buffer[k];
  197. ++k;
  198. }
  199. else text_alpha[i][start_x + j] = 0;/* 否則就置零 */
  200. }
  201. }
  202. start_x += (ch_width+space); /* 畫筆向右邊移動 */
  203. /* 釋放字形占用的內存 */
  204. FT_Done_Glyph(glyph);
  205. glyph = NULL;
  206. }
  207. }
  208. else{
  209. sprintf(error_str,"FreeType2 錯誤[%d]",error);
  210. perror(error_str);
  211. }
  212. }
  213. else{
  214. sprintf(error_str,"FreeType2 錯誤[%d]",error);
  215. perror(error_str);
  216. }
  217. }
  218. /* 釋放face占用的內存 */
  219. FT_Done_Face(p_FT_Face);
  220. p_FT_Face = NULL;
  221. /* 釋放FreeType Lib占用的內存 */
  222. FT_Done_FreeType(p_FT_Lib);
  223. p_FT_Lib = NULL;
  224. temp = 0;
  225. out_fonts->width = text_width; /* 要輸出的位圖的寬度 */
  226. out_fonts->height = bg_height; /* 要輸出的位圖的高度 */
  227. if(out_fonts->malloc == IS_TRUE) free(out_fonts->text_alpha);
  228. size = sizeof(unsigned char) * text_width * bg_height;
  229. out_fonts->text_alpha = (unsigned char*)calloc(1,size); /* 申請內存用來存儲 */
  230. k = 0;
  231. for ( i = 0 ; i < bg_height; ++i)
  232. {
  233. for ( j = 0 ; j < text_width; ++j)
  234. {
  235. out_fonts->text_alpha[k] = text_alpha[i][j];
  236. ++k;
  237. }
  238. }
  239. out_fonts->malloc = IS_TRUE;
  240. /* 釋放內存 */
  241. for(i=0;i<bg_height;++i){
  242. free(text_alpha[i]);
  243. }
  244. free(text_alpha);
  245. free(unicode_text);
  246. return 0;
  247. }

這些代碼在我的工程裡的運行效果:

Copyright © Linux教程網 All Rights Reserved