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

为了简单起见,只显示GB2312(简体中文)字符
一、GB2312汉字编码
1.区位码
在国标GB2312—80中规定,所有的国标汉字及符号分配在一个94行、94列的方阵中,方阵的每一行称为一个“区”,编号为01区到94区,每一列称为一个“位”,编号为01位到94位,方阵中的每一个汉字和符号所在的区号和位号组合在一起形成的四个阿拉伯数字就是它们的“区位码”。区位码的前两位是它的区号,后两位是它的位号。用区位码就可以唯一地确定一个汉字或符号,反过来说,任何一个汉字或符号也都对应着一个唯一的区位码。汉字“母”字的区位码是3624,表明它在方阵的36区24位,问号“?”的区位码为0331,则它在03区31位。
2.机内码
汉字的机内码是指在计算机中表示一个汉字的编码。机内码与区位码稍有区别。如上所述,汉字区位码的区码和位码的取值均在1~94之间,如直接用区位码作为机内码,就会与基本ASCII码混淆。为了避免机内码与基本ASCII码的冲突,需要避开基本ASCII码中的控制码(00H~1FH),还需与基本ASCII码中的字符相区别。为了实现这两点,可以先在区码和位码分别加上20H,在此基础上再加80H(此处“H”表示前两位数字为十六进制数)。经过这些处理,用机内码表示一个汉字需要占两个字节,分别 称为高位字节和低位字节,这两位字节的机内码按如下规则表示:
高位字节 = 区码 + 20H + 80H(或区码 + A0H)
低位字节 = 位码 + 20H + 80H(或位码 + AOH)
由于汉字的区码与位码的取值范围的十六进制数均为01H~5EH(即十进制的01~94),所以汉字的高位字节与低位字节的取值范围则为A1H~FEH(即十进制的161~254)。
例如,汉字“啊”的区位码为1601,区码和位码分别用十六进制表示即为1001H,它的机内码的高位字节为B0H,低位字节为A1H,机内码就是B0A1H。

根据上面的概念,可以使用以下程序将所有的GB2312编码字符保存在一个文件中:

 1 #include <stdio.h>
 2 int main()
 3 {
 4     int area_code,location_code;
 5     unsigned char c[3]={0};
 6     FILE * fp = fopen("gb2312_table.c","wb");
 7     char buf[100];
 8     if(fp)
 9     {
10         sprintf(buf,"#include \"gb2312.h\"\n\nunsigned short gb2312_table[]=\n{\n");
11         fwrite(buf,1,strlen(buf),fp);
12         for(area_code=1;area_code<95;area_code++)//区码为1-94
13         {
14             fputc(‘\t‘,fp);
15             c[0]=area_code + 0xA0;//区码 + A0H 转换为机内码 高字节
16             for(location_code=1;location_code<95;location_code++)//位码为1-94
17             {
18                 c[1]=location_code+0xA0;//位码 + A0H 转换为机内码 低字节
19                 if(area_code == 1 && location_code == 1)
20                     sprintf(buf," 0x%02X%02X",c[0],c[1]);
21                 else
22                     sprintf(buf,",0x%02X%02X",c[0],c[1]);
23                 fwrite(buf,1,strlen(buf),fp);
24             }
25             fputc(‘\n‘,fp);//每区一行
26         }
27         sprintf(buf,"\n};\n\nint GetGB2312TableLen()\n{\n\treturn sizeof(gb2312_table)/sizeof(unsigned short);\n}\n");
28         fwrite(buf,1,strlen(buf),fp);
29         fclose(fp);
30     }
31     return 0;
32 }

这里多生成了一个函数GetGB2312TableLen,用于获取gb2312_table大小。
下面是一个GB2312区位码查询、转换、区位码全表网址:
http://www.mytju.com/classcode/tools/QuWeiMa.asp

二、UNICODE编码

Unicode是一个涵盖了目前全世界使用的所有已知字符的单一编码方案,也就是说Unicode为每一个字符提供唯一的编码。UTF-16是unicode的16位编码方式,是一种定长多字节编码,用2个字节表示一个unicode字符,AF16UTF16是UTF-16编码字符集。
UTF-8是unicode的8位编码方式,是一种变长多字节编码,这种编码可以用1、2、3个字节表示一个unicode字符,AL32UTF8,UTF8、UTFE是UTF-8编码字符集。
为了方便编码之间的转换,下面的实现均在linux下进行,因为在linux下有libiconv库供我们进行编码转换使用,这里还需要注意,通过使用iconv函数转换编码为unicode宽字符时,如果不是转换为utf-16be或者utf-16le指定的字节序,转换后的字符串最前面会多两个字节用于识别unicode字符串的字节序,开头两个字节为FE FF时为Big-Endian,为FF FE时为Little-Endian。
下面是两个编码转换函数,在具体实现中需要包含iconv.h头文件,如果iconv_open函数失败,perror打印错误信息为"无效参数",解决方法参考博:
http://blog.csdn.net/zxwangyun/article/details/9171057
这个函数将UTF8编码字符串转换为GB2312字符串,转换后的每个字符用2Byte存储,高位在前低位在后

 1 static int Utf8ToGb2312(char *sOut, int iMaxOutLen/*BYTE*/, const char *sIn, int iInLen/*BYTE*/)
 2 {
 3     char *pIn = (char *)sIn;
 4     char *pOut = sOut;
 5     size_t ret;
 6     size_t iLeftLen=iMaxOutLen;
 7     iconv_t cd = iconv_open("gb2312", "utf-8");
 8     if (cd == (iconv_t) - 1)
 9     {
10         perror("iconv_open()");
11         return -1;
12     }
13     size_t iSrcLen=iInLen;
14     ret = iconv(cd, &pIn,&iSrcLen, &pOut,&iLeftLen);
15     if (ret == (size_t) - 1)
16     {
17         perror("iconv()");
18         iconv_close(cd);
19         return -1;
20     }
21     iconv_close(cd);
22     return (iMaxOutLen - iLeftLen);
23 }

有些字符串中可能还包含有ASCII字符,转换后的GB2312编码的字符串可用下面的代码进行检测字符为中文还是ASCII字符:

 1     len = Utf8ToGb2312((char*)gb2312,sizeof(gb2312),utf8,strlen(utf8));
 2     printf("UTF8 TEXT LEN:%d converted len=%d\n",strlen(utf8),len);
 3     for(i=0;i<len;i++)
 4     {
 5         if(gb2312[i]<128)//为ANSC字符,每个字符用1个Byte存储
 6         {
 7             printf("ASCII Encode \t-- code:%c \n",gb2312[i]);
 8         }
 9         else//为GB2312(简体中文),每个字用两个Byte存储
10         {
11             printf("GB2312 Encode \t-- Area code:%02d%02d Machine code:0x%04x\n",gb2312[i]- 0xA0,gb2312[i+1]-0xA0,(gb2312[i]<<8)|gb2312[i+1]);
12             i++;//别忘了GB2312字符需要2个Byte
13         }
14     }

这个函数将GB2312编码字符串转换为UTF-16BE(大端字节序)字符串,转换后的每个字符用2Byte存储,高位在前低位在后:

 1 static int Gb2312ToUtf16be(char *sOut, int iMaxOutLen/*BYTE*/, const char *sIn, int iInLen/*BYTE*/)
 2 {
 3     char *pIn = (char *)sIn;
 4     char *pOut = sOut;
 5     size_t ret;
 6     size_t iLeftLen=iMaxOutLen;
 7     iconv_t cd = iconv_open("UTF-16BE", "gb2312");
 8     if (cd == (iconv_t) - 1)
 9     {
10         perror("iconv_open()");
11         return -1;
12     }
13     size_t iSrcLen=iInLen;
14     ret = iconv(cd, &pIn,&iSrcLen, &pOut,&iLeftLen);
15     if (ret == (size_t) - 1)
16     {
17         perror("iconv()");
18         iconv_close(cd);
19         return -1;
20     }
21     iconv_close(cd);
22     return (iMaxOutLen - iLeftLen);
23 }

UNICODE字符串区分ASCII字符和中文字符很简单,如果是UTF-16BE编码的Unicode字符串(每个字符都用2个Byte来存储),只需要看高8位是否为0即可,如果为0,则为ASCII字符。

三、ASCII编码
ASCII字符中的可见字符为33-126(ASCII值)共94个字符(0-31为控制字符,32为空格,略过),以下为94个ascii可见字符:

!"#$%&‘()*+,-./0123456789:;<=>[email protected][\]^_`abcdefghijklmnopqrstuvwxyz{|}~

四、freetype2入门
参看http://blog.chinaunix.net/uid-190095-id-3123383.html中的例子即可对ft2进行简单使用
这里是一个更详细的ft2的文档:http://blog.sina.com.cn/s/blog_4ab2ba570100y7fm.html

五、ffmpeg libswscale库简单使用
libswscale库使用很简单,下面是一个一幅24bit的bmp图片数据转换为yuv数据的例子,这里将yuv数据直接存储在了一个数组并保存在一个文件中.
需要注意的是,如果直接将YUV数据进行显示,可能和原bmp图片相比是上下颠倒的,所以在转换前,最好将该24bit的bmp图片进行垂直翻转后再进行转换.

  1 #include <stdio.h>
  2 #include "bmp_header.h"
  3
  4 //包含swscale.h头文件
  5 #ifdef __cplusplus
  6 extern "C"{
  7 #endif
  8 #include "libavformat/avformat.h"
  9 #include "libswscale/swscale.h"
 10 #ifdef __cplusplus
 11 }
 12 #endif
 13
 14 int save_bgr24_to_yuv420p(const char * src_bmp24_file,const char * dst_yuv_data_file)
 15 {
 16     FILE *fp = NULL;
 17     struct SwsContext *pSwsCtx=NULL;
 18     uint8_t * bmp_data = NULL;
 19     int data_size = 0;
 20     int w=0,h=0;
 21
 22     fp = fopen(src_bmp24_file, "rb");//打开图片
 23     if(fp)
 24     {
 25         // 位图文件头
 26 #ifdef _WIN32
 27         BITMAPFILEHEADER bmpheader={0};
 28         BITMAPINFO bmpinfo={0};
 29         fread(&bmpheader,sizeof(BITMAPFILEHEADER),1,fp);
 30         fread(&bmpinfo.bmiHeader,sizeof(BITMAPINFOHEADER),1,fp);
 31         w = bmpinfo.bmiHeader.biWidth;
 32         h = bmpinfo.bmiHeader.biHeight;
 33         data_size = bmpheader.bfSize - bmpheader.bfOffBits;
 34 #else
 35         FileHead bmp_head;
 36         Infohead bmp_info;
 37         fread(&bmp_head,sizeof(FileHead),1,fp);
 38         fread(&bmp_info,sizeof(Infohead),1,fp);
 39         w = bmp_info.biWidth;
 40         h = bmp_info.biHeight;
 41         data_size = bmp_head.bfSize - bmp_head.bfOffBits;
 42 #endif
 43         if(h<0)h=-h;
 44         if(data_size != w * h * 3)
 45         {
 46             printf("not 24 bit bmp,file size = %d,w=%d,h=%d\n",data_size,w,h);
 47             fclose(fp);
 48             return -1;
 49         }
 50         bmp_data = (uint8_t *)malloc(data_size);
 51         memset(bmp_data,0,data_size);
 52         if(bmp_data)
 53         {
 54             fread(bmp_data,data_size,1,fp);
 55         }
 56         fclose(fp);
 57         fp = NULL;
 58     }
 59     if(bmp_data)
 60     {
 61         pSwsCtx = sws_getContext(
 62             w,
 63             h,
 64             PIX_FMT_BGR24,
 65             w,
 66             h,
 67             PIX_FMT_YUV420P,
 68             SWS_POINT/*SWS_BILINEAR*/,
 69             NULL,
 70             NULL,
 71             NULL);
 72         if(pSwsCtx)
 73         {
 74             uint8_t *data[4]={bmp_data,NULL,NULL,NULL};
 75             int linesize[4]    ={w*3,0,0,0};
 76             int height        = 0;
 77             uint8_t * buffer    = NULL;
 78             AVFrame * yuv_frame = avcodec_alloc_frame();
 79             buffer = (unsigned char *)av_malloc(avpicture_get_size(PIX_FMT_YUV420P,w,h));
 80             memset(buffer,0,avpicture_get_size(PIX_FMT_YUV420P,w,h));
 81             avpicture_fill((AVPicture*)yuv_frame,(uint8_t *)buffer,PIX_FMT_YUV420P,w,h);
 82             height = sws_scale(
 83                 pSwsCtx,
 84                 data,
 85                 linesize,
 86                 0,
 87                 h,
 88                 yuv_frame ->data,
 89                 yuv_frame ->linesize);
 90             fp = fopen(dst_yuv_data_file,"w");
 91             if(fp)
 92             {
 93                 char buf[1024]={0};
 94                 int i=0;
 95                 sprintf(buf,"/*********************Y***************************/\nunsigned char data_Y[]={");
 96                 fwrite(buf,1,strlen(buf),fp);
 97                 for(i=0;i<yuv_frame ->linesize[0]*height;i++)
 98                 {
 99                     if(!(i%16))
100                     {
101                         sprintf(buf,"\n\t");
102                         fwrite(buf,strlen(buf),1,fp);
103                     }
104                     if(i)
105                     {
106                         sprintf(buf,",0x%02X",*(yuv_frame ->data[0]+i));
107                     }
108                     else
109                     {
110                         sprintf(buf," 0x%02X",*(yuv_frame ->data[0]+i));
111                     }
112                     fwrite(buf,strlen(buf),1,fp);
113                 }
114                 sprintf(buf,"\n};\n//%d bytes\n/**************end of Y***************************/\n\n",yuv_frame ->linesize[0]*h);
115                 fwrite(buf,strlen(buf),1,fp);
116                 sprintf(buf,"/********************UV***************************/\nunsigned char data_UV[]={");
117                 fwrite(buf,1,strlen(buf),fp);
118                 for(i=0;i<yuv_frame ->linesize[1]*height/2;i++)
119                 {
120                     if(!(i%8))
121                     {
122                         sprintf(buf,"\n\t");
123                         fwrite(buf,strlen(buf),1,fp);
124                     }
125                     if(i)
126                     {
127                         sprintf(buf,",0x%02X,0x%02X",*(yuv_frame ->data[1]+i),*(yuv_frame ->data[2]+i));
128                     }
129                     else
130                     {
131                         sprintf(buf," 0x%02X,0x%02X",*(yuv_frame ->data[1]+i),*(yuv_frame ->data[2]+i));
132                     }
133                     fwrite(buf,strlen(buf),1,fp);
134                 }
135                 sprintf(buf,"\n};\n//%d bytes\n/*************end of UV***************************/\n\n",yuv_frame ->linesize[1]*h);
136                 fwrite(buf,strlen(buf),1,fp);
137                 fclose(fp);
138                 fp = NULL;
139             }
140             av_free(yuv_frame);
141             av_free(buffer);
142
143             sws_freeContext(pSwsCtx);
144             pSwsCtx = NULL;
145         }
146         free(bmp_data);
147         bmp_data = NULL;
148     }
149     return 0;
150 }

其中bmp_header.h定义linux下的BMP头结构体,定义如下:

 1 #ifndef __BMP_HEADER_H__
 2 #define __BMP_HEADER_H__
 3
 4 #ifndef _WIN32
 5 typedef long BOOL;
 6 typedef long LONG;
 7 typedef unsigned char BYTE;
 8 typedef unsigned long DWORD;
 9 typedef unsigned short WORD;
10 typedef struct {
11     WORD    bfType;//2
12     DWORD   bfSize;//4
13     WORD    bfReserved1;//2
14     WORD    bfReserved2;//2
15     DWORD   bfOffBits;//4
16 }__attribute__((packed))FileHead;
17
18 typedef struct{
19     DWORD      biSize;//4
20     LONG       biWidth;//4
21     LONG       biHeight;//4
22     WORD       biPlanes;//2
23     WORD       biBitCount;//2
24     DWORD      biCompress;//4
25     DWORD      biSizeImage;//4
26     LONG       biXPelsPerMeter;//4
27     LONG       biYPelsPerMeter;//4
28     DWORD      biClrUsed;//4
29     DWORD      biClrImportant;//4
30 }__attribute__((packed))Infohead;
31
32 #endif//_WIN32
33
34 #endif //__BMP_HEADER_H__

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

时间: 2024-11-03 18:50:03

DM36x IPNC OSD显示中文 --- 基础知识篇的相关文章

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

经过上一篇的叙述,基本原理搞清楚后,便需要对我们在OSD上显示中文作数据准备,首先是需要将gb2312关键区(也就是实际有文字存在的区)中的汉字转换为图片,在实际的转换中,并不像上一篇中GB2312编码转换为UNICODE描述一样,使用libiconv库中的iconv函数将94x94的gb2312编码表直接传递给iconv函数会转换失败(错误提示不完整的多字节字符或宽字符).为了简化这其中的转换难度,目前使用的是查表的方法将GB2312编码转换为UNICODE编码,这样就要求先准备好GB2312

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

通过数据准备篇,将数据准备好后,其实剩下的工作已经很简单了,通过以下几个步骤即可把一个中文显示在OSD画面上:1. 使用SWOSD_setBmpchangeWinXYPrm函数设置好OSD显示坐标位置;2. 设置SWOSD_Hndl句柄中SWOSD_BmpWinPrm类型成员数组中对应的窗口的width,height,lineOffset对应的值,width是OSD窗口宽度,如果yuv数据来自的是32x32的bmp图片,则width=n*32,其中n为字符个数,height为OSD窗口高度,li

C#基础知识篇(三)-----------C#笔记

一.方法 1. 什么叫做方法? 方法就是对一段代码的重用的机制. 2. 方法的定义: [访问修饰符] [static] 返回值类型 方法名() { 方法体; } 注意:用[]修饰的都是可选的. 3. 需要注意的细节: 命名规则:方法名开头大写,参数名开头小写,参数名.变量名要有意义. 4. 方法的参数: 1>在方法名后面括号内定义变量就叫做定义这个方法的参数(形参). 2>在方法()中我们定义多个参数时,参数之间用逗号分隔,不管参数之间的类型是否相同,都不能像定义同类型的多个变量时:如:int

C#基础知识篇---------C#笔记

   一.变量         1.什么叫做变量?            我们把值可以改变的量叫做变量.          2.变量的声明:            语法:[访问修饰符] 数据类型 变量名; 如: int number=10://声明了一个整型的变量number.            注意:一次声明多个变量之间要用逗号分隔.                  如:int number1,number2,number3....;          3.变量的赋值:        

Android Camera开发之基础知识篇

概述 Android框架支持设备的相机拍照和录像功能,你的应用可以直接调用系统的Camera应用来拍照或者录像(比如微信拍照),当然也可以利用Android系统提供的API开发一个Camera应用来实现相机拍照和录像功能(比如市面上流行的360相机).此篇文章主要记录相机开发有关的基础知识,以及带着自己的理解翻译Camera官方文档,如有翻译不恰当支出,还请指出改正.当然我会开一个有关相机开发的一个系列,该系列主要内容包括如下: 相机基本预览拍照功能. 实现相机的Flash,Hdr,滤镜,前后摄

C#基础知识篇(五)-----------C#笔记

一.值类型和引用类型 1>值类型和引用类型将我们学过的数据类型划分成了两部分. 划分的依据是不同类型的数据在内存中(堆栈)存储的结构不同. 2>值类型:所有的数值类型:long int short byte ulong uint ushort sbyte decimal duoble float char bool 枚举 结构 3>引用类型:string,arry(数组),类(class) 4>不管是值类型还是引用类型赋值都是将数据copy一份将副本赋给变量,不同的是值类型拷贝的是

C#基础知识篇(二)-----------C#笔记

1.关系运算符(比较运算符) 1.关系运算符有哪些? >,< ==,!= >=,<= 2.关系运算符的作用? 用于比较两个事物之间的关系. 3.什么叫关系表达式? 由关系运算符连接起来的式子叫关系表达式. 注意:所有的关系表达式最终都能计算成一个bool类型的值. 2.逻辑运算符 1.逻辑表达式有哪些? 逻辑与:&& ,逻辑或:||  ,逻辑非:!(又叫取反) 2.逻辑运算 语法:表达式1 逻辑运算符  表达式2 逻辑运算符连接的两个表达式,要最终能求解成一个boo

C#基础知识篇(四)-----------C#笔记

一.类 1. 什么叫做类? 类是具有相同特征的一类事物统称.所以类是一种抽象,即不是一个实体(我们把类看做模板). 2. 什么叫做对象? 对象是根据类的模板创造出来的一个实体,它具有类里所有的特征,一个也多不得,一个也少不得.少了就不叫这个类的成员了,多了也不是!假如张三有变身这个功能,那么张三就不属于人. 记住对象是根据模板创建的,模板有什么它就有什么,不会多也不会少! 3. 什么叫做字段(或者是成员变量)? 我们把定义在方法的外面,类的里面(即:类中)的变量称之为字段或者说是成员变量. 4.

c++基础知识篇:指针

从面试的反馈来看,这部分可以问的很难. 1.指针与引用的区别 指针是一个变量,用来存放地址的变量.引用是原来变量的存储空间的别名. ? 2.指针作为参数的要点 a.需要进行指针的合法性检验,防止空指针. b.需要修改指针本身指向的地址时,参数需要是该指针的引用. ? 3.c++程序运行空间 数据区(Data Area):全局变量.静态变量.常量存放在数据区. 代码区(Code Area):所有类成员函数和非成员函数 栈区(Stack Area):为运行函数分配的局部变量.函数参数.返回数据.返回