zoukankan      html  css  js  c++  java
  • 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 = 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.
    ");
     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.
    ");
     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!
    ");
     44             break;
     45         }
     46 
     47         error = FT_New_Face(library, font_file, 0, &face);
     48         if (error)
     49         {
     50             printf("create new face falied!
    ");
     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!
    ");
     58             break;
     59         }
     60         bmpdata = malloc(font_width * font_height * 3);
     61         if(!bmpdata)
     62         {
     63             printf("outof memory.
    ");
     64             break;
     65         }
     66         image = malloc(94 * font_width * font_height * 3);//这里要求font_size必须为偶数
     67         if(!image)
     68         {
     69             printf("outof memory.
    ");
     70             break;
     71         }
     72 
     73 #if 0
     74         //打印字体相关信息
     75         printf("file has %d faces
    ", face->num_faces);
     76         printf("%s  italic or oblique,%s bold
    ", 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
    ", face->family_name);
     78         printf("file style name %s
    ", face->style_name);
     79         printf("face index %d
    ", face->face_index);
     80         printf("number of char %d
    ", face->num_glyphs);
     81         printf("number of fixed bitmap %d
    ", face->num_fixed_sizes);
     82         printf("Char size %d
    ", face->size);
     83         printf("has %d fixed sizes
    ",face->num_fixed_sizes);
     84         for(i=0;i<face->num_fixed_sizes;i++)
     85         {
     86             printf("supported size %d:width=%d,heigh=%d
    ",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.
    ");
     93             break;
     94         }
     95         //printf("code %x
    ",face ->charmap ->encoding);
     96         switch(face ->charmap ->encoding)
     97         {
     98             case FT_ENCODING_MS_GB2312:    printf("USE GB2312 CODE
    ");break;
     99             case FT_ENCODING_MS_BIG5:    printf("USE BIG5 CODE
    ");break;
    100             case FT_ENCODING_UNICODE:    printf("USE UNICODE CODE
    ");break;
    101             default:
    102                 printf("UNKNOWN CODE
    ");
    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
    ",gb2312_table[index]);
    124                     continue;
    125                 }
    126                 char_code = unicode;
    127                 if(!char_code)
    128                 {
    129                     printf("
    invalidate char code.
    ");
    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("
    load char error!
    ");
    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("
    render char failed!
    ");
    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 0
    164                 //dump位图信息
    165                 printf("bit_map_left %d bit_map_top %d
    ", face->glyph->bitmap_left,face->glyph->bitmap_top);
    166                 printf("int rows:%d
    ",ft_bmp ->rows);
    167                 printf("int %d
    ",ft_bmp ->width);
    168                 printf("int pitch:%d
    ",ft_bmp ->pitch);
    169                 printf("short num_grays:%d
    ",ft_bmp ->num_grays);
    170                 printf("char pixel_mode:%d
    ",ft_bmp ->pixel_mode);
    171                 if(isVert)
    172                 {
    173                     printf("VERT:(w:%ld h:%ld)(bearingX:%ld bearingY:%ld Advance:%ld)
    ",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                 else
    177                 {
    178                     printf("HORI:(w:%ld h:%ld)(bearingX:%ld bearingY:%ld Advance:%ld)
    ",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
    ",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                             else
    203                             {
    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
    ",pitch);
    215                 
    216                             //转换1bit位图数据到24bit位图数据
    217                             printf("begin convert.area %d ----> %d
    ",area,location);
    218                             memset(bmpdata,0,font_width * font_height * 3);
    219                             pdata = 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("
    save bmp file [%s]
    ",testfilename);
    244                                 if(save_bmp24(testfilename,font_width ,font_height,bmpdata))
    245                                 {
    246                                     printf("save bmp file [%s] error.
    ",testfilename);
    247                                 }
    248                             }*/
    249     
    250                         }
    251                         break;
    252                     default:
    253                         printf("位图为非单色图片.
    ");
    254                         goto done;
    255                         break;
    256                 }//switch
    257                 pdata = 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 _WIN32
    266                 usleep(10);
    267 #else
    268                 Sleep(10);
    269 #endif
    270             }//for( 1 - 94 位 )
    271             //保存图片
    272             sprintf(testfilename,"./testbmp/area%d_%dx%d.bmp",area,font_width,font_height);
    273             //printf("
    save bmp file [%s]
    ",testfilename);
    274             if(save_bmp24(testfilename,94 * font_width,font_height,image))
    275             {
    276                 printf("save bmp file [%s] error.
    ",testfilename);
    277             }
    278         }//for( 1 - 94 区)
    279         printf("
    Convert Done.
    ");
    280 
    281     }while (0);
    282 done:
    283 #if 0    //出现莫名其妙的错误,注释了
    284     fprintf(stderr,"begin cleanup.
    ");
    285     if(bmpdata)
    286     {
    287         free(bmpdata);
    288         bmpdata = 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 #endif
    306     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,0x10
    10     ,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10
    11     ,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10
    12 };
    13 //37224 bytes
    14 /**************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,0x80
    19     ,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
    20     ,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
    21     ,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
    22     ......
    23     ,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
    24     ,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
    25     ,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x12,0x92,0x80,0x80,0x80,0x80
    26     ,0x80,0x80,0x80,0x80
    27 };
    28 //18612 bytes
    29 /*************end of UV***************************/

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

  • 相关阅读:
    shell 命名管道,进程间通信
    bash shell:重定向标准错误输出
    paramiko socket.error: Int or String expected
    django csrf_token生成
    shell基础知识
    复制vi全部内容到windows ctrl+shift+c
    linux配置bridge (不同网段)
    sdk shell下脚本.soc
    X86服务器BMC基板管理控制器介绍
    linux 开启vnc
  • 原文地址:https://www.cnblogs.com/eustoma/p/6662101.html
Copyright © 2011-2022 走看看