首页 > 代码库 > DM36x IPNC OSD显示中文 --- 基本数据准备篇

DM36x IPNC OSD显示中文 --- 基本数据准备篇

经过上一篇的叙述,基本原理搞清楚后,便需要对我们在OSD上显示中文作数据准备,
首先是需要将gb2312关键区(也就是实际有文字存在的区)中的汉字转换为图片,在实际的转换中,并不像上一篇中GB2312编码转换为UNICODE描述一样,
使用libiconv库中的iconv函数将94x94的gb2312编码表直接传递给iconv函数会转换失败(错误提示不完整的多字节字符或宽字符).为了简化这其中的转换难度,目前使用的是查表的方法将GB2312编码转换为UNICODE编码,
这样就要求先准备好GB2312 UNICODE对照表,这个表网上有各种形式的,但是通过我花了很长时间查找也没有找到合适自己需求的,主要是网上的GB2312区位码不全,都会丢掉某些区中的某些编码,这样会有个问题,
就是我们转换后的数据需要记录我们中间丢失了哪些编码,对应的位置等等.会造成后续程序执行效率降低和设计难度加大.这里我是直接将94x94个GB2312编码都转换为对应的unicode编码,保存在一个数组中(很占篇幅,这里不贴实际数据了),通过查找下标的方式查找对应的UNICODE编码.
将对应的GB2312编码转换为UNICODE编码后,接下来就是使用Freetype2将该UNICODE码提取出对应的字符映像,并转换为位图,保存在磁盘上了,下面是其中的核心程序:
//linux下保存24位bmp图像,数据结构FileHead、Infohead见上一篇

 1 int save_bmp24(char * filename,int width,int height,unsigned char *data) 2 { 3     FileHead bmp_head; 4     Infohead bmp_info; 5     int size = width*height*3; 6     FILE *fp = fopen(filename,"wb"); 7     if(!fp) 8     { 9         perror("open file error");10         return -1;11     }12 13     bmp_head.bfType=0x4d42;14     bmp_head.bfSize=size+sizeof(FileHead)+sizeof(Infohead);//24+head+info no quad    15     bmp_head.bfReserved1=bmp_head.bfReserved2=0;16     bmp_head.bfOffBits=bmp_head.bfSize-size;17 18     bmp_info.biSize=40;19     bmp_info.biWidth=width;20     bmp_info.biHeight=-height;//如果为正数,转换出来的图片还需要进行垂直翻转21     bmp_info.biPlanes=1;22     bmp_info.biBitCount = 24;23     bmp_info.biCompress=0;24     bmp_info.biSizeImage=size;25     bmp_info.biXPelsPerMeter=0;26     bmp_info.biYPelsPerMeter=0;27     bmp_info.biClrUsed=0;28     bmp_info.biClrImportant=0;29 30     fwrite(&bmp_head,1,sizeof(FileHead),fp);31     fwrite(&bmp_info,1,sizeof(Infohead),fp);32     fwrite(data,1,size,fp);33     fclose(fp);34     return 0;35 }

//转换函数,这里是一个区转换为一个图片

  1 int convert(const char * font_file,int font_width,int font_height)  2 {  3     FT_Library library = NULL;  4     FT_Face face = NULL;  5     int error;  6     int char_index;  7     int char_code;  8       9     unsigned char * bmpdata = http://www.mamicode.com/NULL,*pdata;//保存一个字的图片数据 10     int isVert = 0;//是否垂直布局,中文为垂直布局 11     FT_Bitmap *ft_bmp; 12      13     unsigned short  unicode;//用于存储unicode 14     int index=0; 15     int area,location; 16     char testfilename[100]; 17      18     unsigned char *image = NULL, *pimage;//一个区转换为一张图片 19     int temp; 20      21     if(font_width <= 0 && font_height <= 0) 22     { 23         printf("invalidate font size.\n"); 24         return -1; 25     } 26     if(font_width <= 0) 27         font_width = font_height; 28     if(font_height <= 0) 29         font_height = font_width; 30     if(font_width % 2)//4字节对齐,这里先保证宽度为4pixel对齐 31     { 32         printf("invalidate font size.\n"); 33         return -1; 34     } 35     setlocale(LC_ALL,"zh_CN.UTF-8"); 36  37     do 38     { 39         //下面开始初始化FT2库 40         error = FT_Init_FreeType(&library); 41         if (error) 42         { 43             printf("can not init free type library!\n"); 44             break; 45         } 46  47         error = FT_New_Face(library, font_file, 0, &face); 48         if (error) 49         { 50             printf("create new face falied!\n"); 51             break; 52         } 53         isVert = FT_HAS_VERTICAL(face);     54         error = FT_Set_Pixel_Sizes(face, font_width, font_height);//设置字体大小 55         if (error) 56         { 57             printf("set font size error!\n"); 58             break; 59         } 60         bmpdata = http://www.mamicode.com/malloc(font_width * font_height * 3); 61         if(!bmpdata) 62         { 63             printf("outof memory.\n"); 64             break; 65         } 66         image = malloc(94 * font_width * font_height * 3);//这里要求font_size必须为偶数 67         if(!image) 68         { 69             printf("outof memory.\n"); 70             break; 71         } 72  73 #if 0 74         //打印字体相关信息 75         printf("file has %d faces\n", face->num_faces); 76         printf("%s  italic or oblique,%s bold\n", face->style_flags & FT_STYLE_FLAG_ITALIC ?"support":"not support",face->style_flags & FT_STYLE_FLAG_BOLD ?"support":"not support"); 77         printf("file family name %s\n", face->family_name); 78         printf("file style name %s\n", face->style_name); 79         printf("face index %d\n", face->face_index); 80         printf("number of char %d\n", face->num_glyphs); 81         printf("number of fixed bitmap %d\n", face->num_fixed_sizes); 82         printf("Char size %d\n", face->size); 83         printf("has %d fixed sizes\n",face->num_fixed_sizes); 84         for(i=0;i<face->num_fixed_sizes;i++) 85         { 86             printf("supported size %d:width=%d,heigh=%d\n",i+1,face->available_sizes[i].width,face->available_sizes[i].height); 87         } 88 #endif 89         error = FT_Select_Charmap(face,FT_ENCODING_UNICODE);//这里使用UNICODE映射表,便于使用UNICODE码(char code)来获取char index 90         if(error) 91         { 92             printf("select char map error.\n"); 93             break; 94         } 95         //printf("code %x\n",face ->charmap ->encoding); 96         switch(face ->charmap ->encoding) 97         { 98             case FT_ENCODING_MS_GB2312:    printf("USE GB2312 CODE\n");break; 99             case FT_ENCODING_MS_BIG5:    printf("USE BIG5 CODE\n");break;100             case FT_ENCODING_UNICODE:    printf("USE UNICODE CODE\n");break;101             default:102                 printf("UNKNOWN CODE\n");103                 goto done;104                 break;105         }106         107         //实际有字体的区码为(0-8) (15-86)区(区号从0开始 ) = 9 + 72 = 81个区108         for(area = 0;area < 87;area ++)//1- 87区109         {110             if( (area >8 && area < 15)/* 8 - 15区跳过*/111                 ||(area > 86 && area < 94)/* 87 - 94 区跳过*/112             )113             {114                 continue;115             }116             memset(image,0,94 * font_width * font_height * 3);117             pimage = image;118             for(location = 0;location < 94;location++)//1 - 94位119             {120                 index = area * 94 + location;121                 if(Gb2312ToUnicode(gb2312_table[index],&unicode) < 0)122                 {123                     printf("get unicode code error.gb2312 code 0x%04X\n",gb2312_table[index]);124                     continue;125                 }126                 char_code = unicode;127                 if(!char_code)128                 {129                     printf("\ninvalidate char code.\n");130                     continue;131                 }132                 char_index = FT_Get_Char_Index(face,char_code);133                 error = FT_Load_Glyph(face, char_index,  FT_LOAD_DEFAULT | FT_LOAD_MONOCHROME);134                 if (error)135                 {136                     printf("\nload char error!\n");137                     goto done;138                 }139                 if (face->glyph->format != FT_GLYPH_FORMAT_BITMAP)140                 {141                     error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_MONO);142                     if (error)143                     {144                         printf("\nrender char failed!\n");145                         goto done;146                     }147                 }148 149                 /*150                 单色位图图像数据的表示方法:151                 在单色位图图像中,只有两种颜色,黑色或白色,每一个像素只需要一个比特就能够完成表示,为了清楚比特0或1具体表示哪一种颜色,可以通过查询调色板。152                 在单色位图图像中,调色板只包含两种颜色,每一种颜色用R G B 0 四个字节表示 (在实际的字节流中,顺序是 B G R 0)153                 所以,位图图像数据中的0 代表调色板中 第一种颜色的颜色值, 1 代表调色板中 第二种颜色的颜色值。154                 一行单色位图数据的存储格式规定:155                 每一扫描行的字节数必需是4的整倍数,当不够4的整数倍时,需要加0补齐156                 以 720 × 450 的单色位图图像为例157                 水平扫描行的长度为720,则需要720比特来表示一个扫描行,即需要 720/8=90字节来表示,但是 90不是 4 的整数倍,因此需要用0补齐,直至为4的整数倍,即需要额外的2个填充字节。158                 最终,长度为720的水平扫描行使用了 92 个字节来表示。159                 NOTE:非8位位图可用函数FT_Bitmap_Convert进行转换160                 */161                 //转换为4字节对齐162                 ft_bmp = &face->glyph->bitmap;163 #if 0164                 //dump位图信息165                 printf("bit_map_left %d bit_map_top %d\n", face->glyph->bitmap_left,face->glyph->bitmap_top);166                 printf("int rows:%d\n",ft_bmp ->rows);167                 printf("int width:%d\n",ft_bmp ->width);168                 printf("int pitch:%d\n",ft_bmp ->pitch);169                 printf("short num_grays:%d\n",ft_bmp ->num_grays);170                 printf("char pixel_mode:%d\n",ft_bmp ->pixel_mode);171                 if(isVert)172                 {173                     printf("VERT:(w:%ld h:%ld)(bearingX:%ld bearingY:%ld Advance:%ld)\n",face->glyph->metrics.width/64,face->glyph->metrics.height/64,174                         face->glyph->metrics.vertBearingX/64,face->glyph->metrics.vertBearingY/64,face->glyph->metrics.horiAdvance/64);175                 }176                 else177                 {178                     printf("HORI:(w:%ld h:%ld)(bearingX:%ld bearingY:%ld Advance:%ld)\n",face->glyph->metrics.width/64,face->glyph->metrics.height/64,179                         face->glyph->metrics.horiBearingX/64,face->glyph->metrics.horiBearingY/64,face->glyph->metrics.vertAdvance/64);180                 }181                 printf("xMin=%ld, yMin=%ld, xMax=%ld, yMax=%ld\n",face ->bbox.xMin,face ->bbox.yMin,face ->bbox.xMax,face ->bbox.yMax);182 #endif        183 184                 switch(ft_bmp ->pixel_mode)185                 {186                     case FT_PIXEL_MODE_MONO://单色位图187                         {188                             //将数据转换到24位189                             int topblank     = 0;//字型顶部距离位图顶部空行数目190                             int leftblank     = 0;//字型左边距离位图左边空列数目191                             int rightblank     = 0;//字型右边距离位图右边空列数目192                             int pitch     = 0;//每个扫描行占用几个字节193                             int width    = ft_bmp ->width;//实际字型宽度194                             int height    = ft_bmp ->rows; //实际字型高度195                             unsigned char * ft_bmp_buff = ft_bmp ->buffer;196                             int i,j,k;197                             if(isVert)198                             {199                                 topblank     = face->glyph->metrics.vertBearingY/64;200                                 leftblank     = font_width/2 + face->glyph->metrics.vertBearingX/64;201                             }202                             else203                             {204                                 topblank    = font_height * 2 /3 - face->glyph->metrics.horiBearingY/64;205                                 leftblank     = face->glyph->metrics.horiBearingX/64;206                             }207                             if(topblank < 0)topblank     = 0;208                             if(leftblank < 0)leftblank     = 0;209                             rightblank = font_width - width - leftblank;210                             if(rightblank < 0)rightblank    = 0;211                             pitch =  ft_bmp ->width / 8;212                             if(pitch% ft_bmp ->pitch)213                                 pitch = pitch + (ft_bmp ->pitch - pitch %ft_bmp ->pitch);214                             //printf("PITCH=%d\n",pitch);215                 216                             //转换1bit位图数据到24bit位图数据217                             printf("begin convert.area %d ----> %d\r",area,location);218                             memset(bmpdata,0,font_width * font_height * 3);219                             pdata =http://www.mamicode.com/ bmpdata;220                             pdata += topblank *font_width * 3;//跳过上边距221                             for(i=0;i<height;i++)222                             {223                                 pdata += leftblank * 3;224                                 k = 7;225                                 for(j=0;j<width;j++)226                                 {227                                     if(ft_bmp_buff[j/8] & (1 << k) )228                                     {229                                         //pdata[0] = 255;//230                                         pdata[1] = 255;//绿231                                         pdata[2] = 255;//232                                     }233                                     k--;234                                     if(k<0)k=7;235                                     pdata += 3;236                                 }237                                 ft_bmp_buff += pitch;238                                 pdata += rightblank * 3;239                             }240                             /*if(!(font_width %4))241                             {242                                 sprintf(testfilename,"./testbmp/%d_%d.bmp",area,location );243                                 printf("\nsave bmp file [%s]\n",testfilename);244                                 if(save_bmp24(testfilename,font_width ,font_height,bmpdata))245                                 {246                                     printf("save bmp file [%s] error.\n",testfilename);247                                 }248                             }*/249     250                         }251                         break;252                     default:253                         printf("位图为非单色图片.\n");254                         goto done;255                         break;256                 }//switch257                 pdata =http://www.mamicode.com/ bmpdata;258                 pimage = image + location * font_width * 3;                259                 for(temp=0;temp<font_height;temp++)260                 {261                     memcpy(pimage,pdata,font_width * 3);262                     pdata += font_width * 3;263                     pimage += 94 * font_width *3;264                 }265 #ifndef _WIN32266                 usleep(10);267 #else268                 Sleep(10);269 #endif270             }//for( 1 - 94 位 )271             //保存图片272             sprintf(testfilename,"./testbmp/area%d_%dx%d.bmp",area,font_width,font_height);273             //printf("\nsave bmp file [%s]\n",testfilename);274             if(save_bmp24(testfilename,94 * font_width,font_height,image))275             {276                 printf("save bmp file [%s] error.\n",testfilename);277             }278         }//for( 1 - 94 区)279         printf("\nConvert Done.\n");280 281     }while (0);282 done:283 #if 0    //出现莫名其妙的错误,注释了284     fprintf(stderr,"begin cleanup.\n");285     if(bmpdata)286     {287         free(bmpdata);288         bmpdata =http://www.mamicode.com/ NULL;289     }290     if(image)291     {292         free(image);293         image = NULL;294     }295     if(face)296     {297         FT_Done_Face(face);298         face = NULL;299     }300     if(library)301     {302         FT_Done_FreeType(library);303         library = NULL;304     }305 #endif306     return 0;307 }

这里上传几个程序转换的图片:

14x16:

技术分享

16x18:

技术分享
20x24:
技术分享
28x32:
技术分享
将编码转换为图片后,需要将bmp24图片数据转换为yuv420p数据,利用libswscale库进行转换的核心代码已经在上一篇贴了,这里不再重贴.
下面是转换后的结果,当然也可以直接将数据保存为一个二进制文件,而不是一个C源程序文件

 1 /*********************Y***************************/ 2 unsigned char data_Y[]={ 3      0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10 4     ,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10 5     ,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10 6     ,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10 7     ...... 8     ,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10 9     ,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x1010     ,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x1011     ,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x1012 };13 //37224 bytes14 /**************end of Y***************************/15 16 /********************UV***************************/17 unsigned char data_UV[]={18      0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x8019     ,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x8020     ,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x8021     ,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x8022     ......23     ,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x8024     ,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x8025     ,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x12,0x92,0x80,0x80,0x80,0x8026     ,0x80,0x80,0x80,0x8027 };28 //18612 bytes29 /*************end of UV***************************/

http://blog.csdn.net/sloan6/article/details/9231373

DM36x IPNC OSD显示中文 --- 基本数据准备篇