经过上一篇的叙述,基本原理搞清楚后,便需要对我们在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见上一篇

 int save_bmp24(char * filename,int width,int height,unsigned char *data)
{
FileHead bmp_head;
Infohead bmp_info;
int size = width*height*;
FILE *fp = fopen(filename,"wb");
if(!fp)
{
perror("open file error");
return -;
} bmp_head.bfType=0x4d42;
bmp_head.bfSize=size+sizeof(FileHead)+sizeof(Infohead);//24+head+info no quad
bmp_head.bfReserved1=bmp_head.bfReserved2=;
bmp_head.bfOffBits=bmp_head.bfSize-size; bmp_info.biSize=;
bmp_info.biWidth=width;
bmp_info.biHeight=-height;//如果为正数,转换出来的图片还需要进行垂直翻转
bmp_info.biPlanes=;
bmp_info.biBitCount = ;
bmp_info.biCompress=;
bmp_info.biSizeImage=size;
bmp_info.biXPelsPerMeter=;
bmp_info.biYPelsPerMeter=;
bmp_info.biClrUsed=;
bmp_info.biClrImportant=; fwrite(&bmp_head,,sizeof(FileHead),fp);
fwrite(&bmp_info,,sizeof(Infohead),fp);
fwrite(data,,size,fp);
fclose(fp);
return ;
}

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

 int convert(const char * font_file,int font_width,int font_height)
{
FT_Library library = NULL;
FT_Face face = NULL;
int error;
int char_index;
int char_code; unsigned char * bmpdata = NULL,*pdata;//保存一个字的图片数据
int isVert = ;//是否垂直布局,中文为垂直布局
FT_Bitmap *ft_bmp; unsigned short unicode;//用于存储unicode
int index=;
int area,location;
char testfilename[]; unsigned char *image = NULL, *pimage;//一个区转换为一张图片
int temp; if(font_width <= && font_height <= )
{
printf("invalidate font size.\n");
return -;
}
if(font_width <= )
font_width = font_height;
if(font_height <= )
font_height = font_width;
if(font_width % )//4字节对齐,这里先保证宽度为4pixel对齐
{
printf("invalidate font size.\n");
return -;
}
setlocale(LC_ALL,"zh_CN.UTF-8"); do
{
//下面开始初始化FT2库
error = FT_Init_FreeType(&library);
if (error)
{
printf("can not init free type library!\n");
break;
} error = FT_New_Face(library, font_file, , &face);
if (error)
{
printf("create new face falied!\n");
break;
}
isVert = FT_HAS_VERTICAL(face);
error = FT_Set_Pixel_Sizes(face, font_width, font_height);//设置字体大小
if (error)
{
printf("set font size error!\n");
break;
}
bmpdata = malloc(font_width * font_height * );
if(!bmpdata)
{
printf("outof memory.\n");
break;
}
image = malloc( * font_width * font_height * );//这里要求font_size必须为偶数
if(!image)
{
printf("outof memory.\n");
break;
} #if 0
//打印字体相关信息
printf("file has %d faces\n", face->num_faces);
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");
printf("file family name %s\n", face->family_name);
printf("file style name %s\n", face->style_name);
printf("face index %d\n", face->face_index);
printf("number of char %d\n", face->num_glyphs);
printf("number of fixed bitmap %d\n", face->num_fixed_sizes);
printf("Char size %d\n", face->size);
printf("has %d fixed sizes\n",face->num_fixed_sizes);
for(i=;i<face->num_fixed_sizes;i++)
{
printf("supported size %d:width=%d,heigh=%d\n",i+,face->available_sizes[i].width,face->available_sizes[i].height);
}
#endif
error = FT_Select_Charmap(face,FT_ENCODING_UNICODE);//这里使用UNICODE映射表,便于使用UNICODE码(char code)来获取char index
if(error)
{
printf("select char map error.\n");
break;
}
//printf("code %x\n",face ->charmap ->encoding);
switch(face ->charmap ->encoding)
{
case FT_ENCODING_MS_GB2312: printf("USE GB2312 CODE\n");break;
case FT_ENCODING_MS_BIG5: printf("USE BIG5 CODE\n");break;
case FT_ENCODING_UNICODE: printf("USE UNICODE CODE\n");break;
default:
printf("UNKNOWN CODE\n");
goto done;
break;
} //实际有字体的区码为(0-8) (15-86)区(区号从0开始 ) = 9 + 72 = 81个区
for(area = ;area < ;area ++)//1- 87区
{
if( (area > && area < )/* 8 - 15区跳过*/
||(area > && area < )/* 87 - 94 区跳过*/
)
{
continue;
}
memset(image,, * font_width * font_height * );
pimage = image;
for(location = ;location < ;location++)//1 - 94位
{
index = area * + location;
if(Gb2312ToUnicode(gb2312_table[index],&unicode) < )
{
printf("get unicode code error.gb2312 code 0x%04X\n",gb2312_table[index]);
continue;
}
char_code = unicode;
if(!char_code)
{
printf("\ninvalidate char code.\n");
continue;
}
char_index = FT_Get_Char_Index(face,char_code);
error = FT_Load_Glyph(face, char_index, FT_LOAD_DEFAULT | FT_LOAD_MONOCHROME);
if (error)
{
printf("\nload char error!\n");
goto done;
}
if (face->glyph->format != FT_GLYPH_FORMAT_BITMAP)
{
error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_MONO);
if (error)
{
printf("\nrender char failed!\n");
goto done;
}
} /*
单色位图图像数据的表示方法:
在单色位图图像中,只有两种颜色,黑色或白色,每一个像素只需要一个比特就能够完成表示,为了清楚比特0或1具体表示哪一种颜色,可以通过查询调色板。
在单色位图图像中,调色板只包含两种颜色,每一种颜色用R G B 0 四个字节表示 (在实际的字节流中,顺序是 B G R 0)
所以,位图图像数据中的0 代表调色板中 第一种颜色的颜色值, 1 代表调色板中 第二种颜色的颜色值。
一行单色位图数据的存储格式规定:
每一扫描行的字节数必需是4的整倍数,当不够4的整数倍时,需要加0补齐
以 720 × 450 的单色位图图像为例
水平扫描行的长度为720,则需要720比特来表示一个扫描行,即需要 720/8=90字节来表示,但是 90不是 4 的整数倍,因此需要用0补齐,直至为4的整数倍,即需要额外的2个填充字节。
最终,长度为720的水平扫描行使用了 92 个字节来表示。
NOTE:非8位位图可用函数FT_Bitmap_Convert进行转换
*/
//转换为4字节对齐
ft_bmp = &face->glyph->bitmap;
#if 0
//dump位图信息
printf("bit_map_left %d bit_map_top %d\n", face->glyph->bitmap_left,face->glyph->bitmap_top);
printf("int rows:%d\n",ft_bmp ->rows);
printf("int width:%d\n",ft_bmp ->width);
printf("int pitch:%d\n",ft_bmp ->pitch);
printf("short num_grays:%d\n",ft_bmp ->num_grays);
printf("char pixel_mode:%d\n",ft_bmp ->pixel_mode);
if(isVert)
{
printf("VERT:(w:%ld h:%ld)(bearingX:%ld bearingY:%ld Advance:%ld)\n",face->glyph->metrics.width/,face->glyph->metrics.height/,
face->glyph->metrics.vertBearingX/,face->glyph->metrics.vertBearingY/,face->glyph->metrics.horiAdvance/);
}
else
{
printf("HORI:(w:%ld h:%ld)(bearingX:%ld bearingY:%ld Advance:%ld)\n",face->glyph->metrics.width/,face->glyph->metrics.height/,
face->glyph->metrics.horiBearingX/,face->glyph->metrics.horiBearingY/,face->glyph->metrics.vertAdvance/);
}
printf("xMin=%ld, yMin=%ld, xMax=%ld, yMax=%ld\n",face ->bbox.xMin,face ->bbox.yMin,face ->bbox.xMax,face ->bbox.yMax);
#endif switch(ft_bmp ->pixel_mode)
{
case FT_PIXEL_MODE_MONO://单色位图
{
//将数据转换到24位
int topblank = ;//字型顶部距离位图顶部空行数目
int leftblank = ;//字型左边距离位图左边空列数目
int rightblank = ;//字型右边距离位图右边空列数目
int pitch = ;//每个扫描行占用几个字节
int width = ft_bmp ->width;//实际字型宽度
int height = ft_bmp ->rows; //实际字型高度
unsigned char * ft_bmp_buff = ft_bmp ->buffer;
int i,j,k;
if(isVert)
{
topblank = face->glyph->metrics.vertBearingY/;
leftblank = font_width/ + face->glyph->metrics.vertBearingX/;
}
else
{
topblank = font_height * / - face->glyph->metrics.horiBearingY/;
leftblank = face->glyph->metrics.horiBearingX/;
}
if(topblank < )topblank = ;
if(leftblank < )leftblank = ;
rightblank = font_width - width - leftblank;
if(rightblank < )rightblank = ;
pitch = ft_bmp ->width / ;
if(pitch% ft_bmp ->pitch)
pitch = pitch + (ft_bmp ->pitch - pitch %ft_bmp ->pitch);
//printf("PITCH=%d\n",pitch); //转换1bit位图数据到24bit位图数据
printf("begin convert.area %d ----> %d\r",area,location);
memset(bmpdata,,font_width * font_height * );
pdata = bmpdata;
pdata += topblank *font_width * ;//跳过上边距
for(i=;i<height;i++)
{
pdata += leftblank * ;
k = ;
for(j=;j<width;j++)
{
if(ft_bmp_buff[j/] & ( << k) )
{
//pdata[0] = 255;//蓝
pdata[] = ;//绿
pdata[] = ;//红
}
k--;
if(k<)k=;
pdata += ;
}
ft_bmp_buff += pitch;
pdata += rightblank * ;
}
/*if(!(font_width %4))
{
sprintf(testfilename,"./testbmp/%d_%d.bmp",area,location );
printf("\nsave bmp file [%s]\n",testfilename);
if(save_bmp24(testfilename,font_width ,font_height,bmpdata))
{
printf("save bmp file [%s] error.\n",testfilename);
}
}*/ }
break;
default:
printf("位图为非单色图片.\n");
goto done;
break;
}//switch
pdata = bmpdata;
pimage = image + location * font_width * ;
for(temp=;temp<font_height;temp++)
{
memcpy(pimage,pdata,font_width * );
pdata += font_width * ;
pimage += * font_width *;
}
#ifndef _WIN32
usleep();
#else
Sleep();
#endif
}//for( 1 - 94 位 )
//保存图片
sprintf(testfilename,"./testbmp/area%d_%dx%d.bmp",area,font_width,font_height);
//printf("\nsave bmp file [%s]\n",testfilename);
if(save_bmp24(testfilename, * font_width,font_height,image))
{
printf("save bmp file [%s] error.\n",testfilename);
}
}//for( 1 - 94 区)
printf("\nConvert Done.\n"); }while ();
done:
#if 0 //出现莫名其妙的错误,注释了
fprintf(stderr,"begin cleanup.\n");
if(bmpdata)
{
free(bmpdata);
bmpdata = NULL;
}
if(image)
{
free(image);
image = NULL;
}
if(face)
{
FT_Done_Face(face);
face = NULL;
}
if(library)
{
FT_Done_FreeType(library);
library = NULL;
}
#endif
return ;
}

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

14x16:

16x18:


20x24:

28x32:

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

 /*********************Y***************************/
unsigned char data_Y[]={
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10
,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10
,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10
,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10
......
,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10
,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10
,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10
,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10
};
//37224 bytes
/**************end of Y***************************/ /********************UV***************************/
unsigned char data_UV[]={
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
......
,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x12,0x92,0x80,0x80,0x80,0x80
,0x80,0x80,0x80,0x80
};
//18612 bytes
/*************end of UV***************************/

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

DM36x IPNC OSD显示中文 --- 基本数据准备篇的更多相关文章

  1. DM36x IPNC OSD显示中文 --- 基础知识篇

    为了简单起见,只显示GB2312(简体中文)字符一.GB2312汉字编码1.区位码在国标GB2312—80中规定,所有的国标汉字及符号分配在一个94行.94列的方阵中,方阵的每一行称为一个“区”,编号 ...

  2. DM36x IPNC OSD显示中文 --- 实战篇

    通过数据准备篇,将数据准备好后,其实剩下的工作已经很简单了,通过以下几个步骤即可把一个中文显示在OSD画面上:1. 使用SWOSD_setBmpchangeWinXYPrm函数设置好OSD显示坐标位置 ...

  3. [daily][troubleshoot][archlinux][wps][font] wps文档中的图内容无法显示中文

    序 用linux作为工作生产环境的几个需要解决的问题之一是:文档协作,即如何兼容Micro$oft Office格式的文档. 我一般的工作方式是:在linux下创建一个win7的虚拟机,安装常用的wi ...

  4. C#基础系列:开发自己的窗体设计器(PropertyGrid显示中文属性名)

    既然是一个窗体设计器,那就应该能够设置控件的属性,设置属性最好的当然是PropertyGrid了,我们仅仅需要使用一个PropertyGrid.SelectedObject = Control就可以搞 ...

  5. OSG和osgearth显示中文(转载)

    osgEarth支持中文过程详解 OSG和osgearth显示中文 一.知识储备   要想很好的理解和解决这个问题,首先要了解什么是多字节和宽字节.说实话我之前也知道这两个字节到底有什么区别,只是简单 ...

  6. RoportNG报表显示中文乱码和TestNG显示中文乱码实力解决办法

    最近在进军测试自动化框架学习阶段,但无意间总是会伴随小问题的困扰,比如中文乱码,而导致显示总是不舒服,个人觉得,就一定要解决,似乎有点点强迫症.所以遇到RoportNG报表显示中文乱码和TestNG显 ...

  7. 基于Windows环境下cmd/编译器无法输入中文,显示中文乱码解决方案

    基于Windows环境下cmd/编译器无法输入中文,显示中文乱码解决方案 两个月前做C++课设的时候,电脑编译器编译结果出现了中文乱码,寻求了百度和大神们,都没有解决这个问题,百度上一堆解释是对编译器 ...

  8. ubuntu下使用matplotlib绘图无法显示中文label

    原因是字体导致的.大家的做法基本都是搞一个windows上的字体文件(simhei.ttf, 点我fq下载)然后刷新一下缓存文件. 只不过百度搜到第一篇CSDN的博客,写的很不靠谱(不是所有的CSDN ...

  9. ReportNG报表显示中文乱码和TestNG显示中文乱码实力解决办法

    最近在进军测试自动化框架学习阶段,但无意间总是会伴随小问题的困扰,比如中文乱码,而导致显示总是不舒服,个人觉得,就一定要解决,似乎有点点强迫症.所以遇到ReportNG报表显示中文乱码和TestNG显 ...

随机推荐

  1. 微信小程序开发教程(一)准备

    1.成为微信公众平台开发者 成为微信公众平台的开发者,是小程序开发的首要条件.只有成为微信公众平台的开发者,才可以使用公众平台的各种开发接口.如果你已经是开发者,则可以跳过本章. ①.进入微信公众平台 ...

  2. [BZOJ2876]骑行川藏

    以前并没有发现微积分教材上有这种东西...我还是太菜了... 其实就是要在满足$\sum\limits_{i=1}^nk_is_i(v_i-v_i')^2\leq E$的同时求$\sum\limits ...

  3. [Contest20180314]数列

    数据范围告诉我们要写两档的分 第一档:$M\leq200,N\leq10^9$,可以枚举$m$计算答案 直接矩阵快速幂:$O\left(M^4\log_2N\right)$,会超时,所以我们需要某些“ ...

  4. 【AC自动机】【动态规划】hdu2296 Ring

    题解:http://www.cnblogs.com/swm8023/archive/2012/08/08/2627535.html 要输出路径,价值最大优先,价值相同的取长度较小者,仍相同取字典序较小 ...

  5. 【Treap】BZOJ1588-[HNOI2002]营业额统计

    [题目大意][借用别人的概括]给出一个n个数的数列a,对于第i个元素ai定义fi=min(abs(ai-aj)),(1<=j<i),其中f1=a1.输出sum(fi) (1<=i&l ...

  6. [美团 CodeM 初赛 Round A]数列互质

    题目大意: 给出一个长度为n的数列a1,a2,a3,...,an,以及m组询问(li,ri,ki),求区间[li,ri]中有多少数在该区间中的出现次数与ki互质. 思路: 莫队. f[i]记录数字i出 ...

  7. 简单php连接数据库作操作

    1.近期稳定版本 <?php header('Content-Type: application/json'); $output = []; $host = ''; //MySQL服务器地址 $ ...

  8. tengine + lua 实现流量拷贝

    环境搭建参考地址:http://www.cnblogs.com/cp-miao/p/7505910.html cp.lua local res1, res2, action action = ngx. ...

  9. 织梦默认分页样式改动 解决分页列表显示,去掉li

    近期装了个织梦dedecmsV5.7版本号时,调用分页显示出现的结果出现好几行,怎么也不能在一排显示,找了非常多资料,才了解到是由织梦模板中分页加了<Li>列表标签,解决有两种方法,以下将 ...

  10. windows 7系统搭建PHP网站环境

    2.新建数据库打开浏览器,输入http://localhost:9999或者http://127.0.0.1:9999回车填写用户名root和密码回车登录点击权限-添加新用户填写用户名,主机选择本地, ...