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编码字符保存在一个文件中:
#include <stdio.h>
int main()
{
int area_code,location_code;
unsigned char c[]={};
FILE * fp = fopen("gb2312_table.c","wb");
char buf[];
if(fp)
{
sprintf(buf,"#include \"gb2312.h\"\n\nunsigned short gb2312_table[]=\n{\n");
fwrite(buf,,strlen(buf),fp);
for(area_code=;area_code<;area_code++)//区码为1-94
{
fputc('\t',fp);
c[]=area_code + 0xA0;//区码 + A0H 转换为机内码 高字节
for(location_code=;location_code<;location_code++)//位码为1-94
{
c[]=location_code+0xA0;//位码 + A0H 转换为机内码 低字节
if(area_code == && location_code == )
sprintf(buf," 0x%02X%02X",c[],c[]);
else
sprintf(buf,",0x%02X%02X",c[],c[]);
fwrite(buf,,strlen(buf),fp);
}
fputc('\n',fp);//每区一行
}
sprintf(buf,"\n};\n\nint GetGB2312TableLen()\n{\n\treturn sizeof(gb2312_table)/sizeof(unsigned short);\n}\n");
fwrite(buf,,strlen(buf),fp);
fclose(fp);
}
return ;
}
这里多生成了一个函数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存储,高位在前低位在后
static int Utf8ToGb2312(char *sOut, int iMaxOutLen/*BYTE*/, const char *sIn, int iInLen/*BYTE*/)
{
char *pIn = (char *)sIn;
char *pOut = sOut;
size_t ret;
size_t iLeftLen=iMaxOutLen;
iconv_t cd = iconv_open("gb2312", "utf-8");
if (cd == (iconv_t) - )
{
perror("iconv_open()");
return -;
}
size_t iSrcLen=iInLen;
ret = iconv(cd, &pIn,&iSrcLen, &pOut,&iLeftLen);
if (ret == (size_t) - )
{
perror("iconv()");
iconv_close(cd);
return -;
}
iconv_close(cd);
return (iMaxOutLen - iLeftLen);
}
有些字符串中可能还包含有ASCII字符,转换后的GB2312编码的字符串可用下面的代码进行检测字符为中文还是ASCII字符:
len = Utf8ToGb2312((char*)gb2312,sizeof(gb2312),utf8,strlen(utf8));
printf("UTF8 TEXT LEN:%d converted len=%d\n",strlen(utf8),len);
for(i=;i<len;i++)
{
if(gb2312[i]<)//为ANSC字符,每个字符用1个Byte存储
{
printf("ASCII Encode \t-- code:%c \n",gb2312[i]);
}
else//为GB2312(简体中文),每个字用两个Byte存储
{
printf("GB2312 Encode \t-- Area code:%02d%02d Machine code:0x%04x\n",gb2312[i]- 0xA0,gb2312[i+]-0xA0,(gb2312[i]<<)|gb2312[i+]);
i++;//别忘了GB2312字符需要2个Byte
}
}
这个函数将GB2312编码字符串转换为UTF-16BE(大端字节序)字符串,转换后的每个字符用2Byte存储,高位在前低位在后:
static int Gb2312ToUtf16be(char *sOut, int iMaxOutLen/*BYTE*/, const char *sIn, int iInLen/*BYTE*/)
{
char *pIn = (char *)sIn;
char *pOut = sOut;
size_t ret;
size_t iLeftLen=iMaxOutLen;
iconv_t cd = iconv_open("UTF-16BE", "gb2312");
if (cd == (iconv_t) - )
{
perror("iconv_open()");
return -;
}
size_t iSrcLen=iInLen;
ret = iconv(cd, &pIn,&iSrcLen, &pOut,&iLeftLen);
if (ret == (size_t) - )
{
perror("iconv()");
iconv_close(cd);
return -;
}
iconv_close(cd);
return (iMaxOutLen - iLeftLen);
}
UNICODE字符串区分ASCII字符和中文字符很简单,如果是UTF-16BE编码的Unicode字符串(每个字符都用2个Byte来存储),只需要看高8位是否为0即可,如果为0,则为ASCII字符。
三、ASCII编码
ASCII字符中的可见字符为33-126(ASCII值)共94个字符(0-31为控制字符,32为空格,略过),以下为94个ascii可见字符:
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`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图片进行垂直翻转后再进行转换.
#include <stdio.h>
#include "bmp_header.h" //包含swscale.h头文件
#ifdef __cplusplus
extern "C"{
#endif
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#ifdef __cplusplus
}
#endif int save_bgr24_to_yuv420p(const char * src_bmp24_file,const char * dst_yuv_data_file)
{
FILE *fp = NULL;
struct SwsContext *pSwsCtx=NULL;
uint8_t * bmp_data = NULL;
int data_size = ;
int w=,h=; fp = fopen(src_bmp24_file, "rb");//打开图片
if(fp)
{
// 位图文件头
#ifdef _WIN32
BITMAPFILEHEADER bmpheader={};
BITMAPINFO bmpinfo={};
fread(&bmpheader,sizeof(BITMAPFILEHEADER),,fp);
fread(&bmpinfo.bmiHeader,sizeof(BITMAPINFOHEADER),,fp);
w = bmpinfo.bmiHeader.biWidth;
h = bmpinfo.bmiHeader.biHeight;
data_size = bmpheader.bfSize - bmpheader.bfOffBits;
#else
FileHead bmp_head;
Infohead bmp_info;
fread(&bmp_head,sizeof(FileHead),,fp);
fread(&bmp_info,sizeof(Infohead),,fp);
w = bmp_info.biWidth;
h = bmp_info.biHeight;
data_size = bmp_head.bfSize - bmp_head.bfOffBits;
#endif
if(h<)h=-h;
if(data_size != w * h * )
{
printf("not 24 bit bmp,file size = %d,w=%d,h=%d\n",data_size,w,h);
fclose(fp);
return -;
}
bmp_data = (uint8_t *)malloc(data_size);
memset(bmp_data,,data_size);
if(bmp_data)
{
fread(bmp_data,data_size,,fp);
}
fclose(fp);
fp = NULL;
}
if(bmp_data)
{
pSwsCtx = sws_getContext(
w,
h,
PIX_FMT_BGR24,
w,
h,
PIX_FMT_YUV420P,
SWS_POINT/*SWS_BILINEAR*/,
NULL,
NULL,
NULL);
if(pSwsCtx)
{
uint8_t *data[]={bmp_data,NULL,NULL,NULL};
int linesize[] ={w*,,,};
int height = ;
uint8_t * buffer = NULL;
AVFrame * yuv_frame = avcodec_alloc_frame();
buffer = (unsigned char *)av_malloc(avpicture_get_size(PIX_FMT_YUV420P,w,h));
memset(buffer,,avpicture_get_size(PIX_FMT_YUV420P,w,h));
avpicture_fill((AVPicture*)yuv_frame,(uint8_t *)buffer,PIX_FMT_YUV420P,w,h);
height = sws_scale(
pSwsCtx,
data,
linesize,
,
h,
yuv_frame ->data,
yuv_frame ->linesize);
fp = fopen(dst_yuv_data_file,"w");
if(fp)
{
char buf[]={};
int i=;
sprintf(buf,"/*********************Y***************************/\nunsigned char data_Y[]={");
fwrite(buf,,strlen(buf),fp);
for(i=;i<yuv_frame ->linesize[]*height;i++)
{
if(!(i%))
{
sprintf(buf,"\n\t");
fwrite(buf,strlen(buf),,fp);
}
if(i)
{
sprintf(buf,",0x%02X",*(yuv_frame ->data[]+i));
}
else
{
sprintf(buf," 0x%02X",*(yuv_frame ->data[]+i));
}
fwrite(buf,strlen(buf),,fp);
}
sprintf(buf,"\n};\n//%d bytes\n/**************end of Y***************************/\n\n",yuv_frame ->linesize[]*h);
fwrite(buf,strlen(buf),,fp);
sprintf(buf,"/********************UV***************************/\nunsigned char data_UV[]={");
fwrite(buf,,strlen(buf),fp);
for(i=;i<yuv_frame ->linesize[]*height/;i++)
{
if(!(i%))
{
sprintf(buf,"\n\t");
fwrite(buf,strlen(buf),,fp);
}
if(i)
{
sprintf(buf,",0x%02X,0x%02X",*(yuv_frame ->data[]+i),*(yuv_frame ->data[]+i));
}
else
{
sprintf(buf," 0x%02X,0x%02X",*(yuv_frame ->data[]+i),*(yuv_frame ->data[]+i));
}
fwrite(buf,strlen(buf),,fp);
}
sprintf(buf,"\n};\n//%d bytes\n/*************end of UV***************************/\n\n",yuv_frame ->linesize[]*h);
fwrite(buf,strlen(buf),,fp);
fclose(fp);
fp = NULL;
}
av_free(yuv_frame);
av_free(buffer); sws_freeContext(pSwsCtx);
pSwsCtx = NULL;
}
free(bmp_data);
bmp_data = NULL;
}
return ;
}
其中bmp_header.h定义linux下的BMP头结构体,定义如下:
#ifndef __BMP_HEADER_H__
#define __BMP_HEADER_H__ #ifndef _WIN32
typedef long BOOL;
typedef long LONG;
typedef unsigned char BYTE;
typedef unsigned long DWORD;
typedef unsigned short WORD;
typedef struct {
WORD bfType;//
DWORD bfSize;//
WORD bfReserved1;//
WORD bfReserved2;//
DWORD bfOffBits;//
}__attribute__((packed))FileHead; typedef struct{
DWORD biSize;//
LONG biWidth;//
LONG biHeight;//
WORD biPlanes;//
WORD biBitCount;//
DWORD biCompress;//
DWORD biSizeImage;//
LONG biXPelsPerMeter;//
LONG biYPelsPerMeter;//
DWORD biClrUsed;//
DWORD biClrImportant;//
}__attribute__((packed))Infohead; #endif//_WIN32 #endif //__BMP_HEADER_H__
http://blog.csdn.net/sloan6/article/details/9231337
DM36x IPNC OSD显示中文 --- 基础知识篇的更多相关文章
- DM36x IPNC OSD显示中文 --- 基本数据准备篇
经过上一篇的叙述,基本原理搞清楚后,便需要对我们在OSD上显示中文作数据准备,首先是需要将gb2312关键区(也就是实际有文字存在的区)中的汉字转换为图片,在实际的转换中,并不像上一篇中GB2312编 ...
- DM36x IPNC OSD显示中文 --- 实战篇
通过数据准备篇,将数据准备好后,其实剩下的工作已经很简单了,通过以下几个步骤即可把一个中文显示在OSD画面上:1. 使用SWOSD_setBmpchangeWinXYPrm函数设置好OSD显示坐标位置 ...
- 【Java面试】基础知识篇
[Java面试]基础知识篇 Java基础知识总结,主要包括数据类型,string类,集合,线程,时间,正则,流,jdk5--8各个版本的新特性,等等.不足的地方,欢迎大家补充.源码分享见个人公告.Ja ...
- 【Java面试】1、基础知识篇
[Java面试]基础知识篇 Java基础知识总结,主要包括数据类型,string类,集合,线程,时间,正则,流,jdk5--8各个版本的新特性,等等.不足的地方,欢迎大家补充. 源码分享:https: ...
- Java白皮书学习笔记+Head First Java--用于自我复习 基础知识篇
本笔记是摘与Hava白皮书上面的内容,用来给自己做提醒的,因此大概并不适合Java的学习者作为笔记参考使用. 以我的水平现在还看不懂这个... 一.基础知识篇 1.常量 final关键字指示常量,只能 ...
- Java 面试知识点解析(一)——基础知识篇
前言: 在遨游了一番 Java Web 的世界之后,发现了自己的一些缺失,所以就着一篇深度好文:知名互联网公司校招 Java 开发岗面试知识点解析 ,来好好的对 Java 知识点进行复习和学习一番,大 ...
- CSS3 的box-shadow进阶之 - 基础知识篇
box-shadow被认为是CSS3最好的特性之一,发挥想象力,搭配其它属性,可以做出很多好看的效果(如下图,将会放在下一篇文章讲解),这篇文章主要讲一下box-shadow的基础知识. ...
- LeetCode刷题191130 --基础知识篇 二叉搜索树
休息了两天,状态恢复了一下,补充点基础知识. 二叉搜索树 搜索树数据结构支持许多动态集合操作,包括Search,minimum,maximum,predecessor(前驱),successor(后继 ...
- 「Java面试题/知识点精华集」20000+字的Java基础知识篇(2020最新版) !
本文已经收录进我的 79K Star 的 Java 开源项目 JavaGuide:https://github.com/Snailclimb/JavaGuide (「Java学习+面试指南」一份涵盖大 ...
随机推荐
- POJ 3293 Rectilinear polygon(几何基础)
[题目链接] http://poj.org/problem?id=3293 [题目大意] 给出一些点,每个点只能向外引出一条平行X轴,和Y轴的边, 问能否构成一个闭多边形,如果能,返回多边形的总边长, ...
- 【博弈论】bzoj2463 [中山市选2009]谁能赢呢?
∵都是最优操作 ∴n*n=偶数时Bob赢,否则Alice赢 n*n的奇偶性等价于n的奇偶性. #include<cstdio> using namespace std; int n; in ...
- 【R笔记】apply函数族
(1) apply apply函数通过对数组,矩阵,或非空维数值的数据框的“边缘”(margin)即行或列运用函数.返回值为向量,数组或列表. 函数形式 apply(X, MARGIN, ...
- Python+C混编
Python最慢!C最快!Python+C混编?结果可想而知! 樱桃种子 百家号04-1712:11 共享库 使用C语言编译产生共享库,然后python使用ctype库里的cdll来打开共享库. 举例 ...
- CAP 定理的含义
分布式系统(distributed system)正变得越来越重要,大型网站几乎都是分布式的. 分布式系统的最大难点,就是各个节点的状态如何同步.CAP 定理是这方面的基本定理,也是理解分布式系统的起 ...
- 警惕rapidxml的陷阱(二):在Android上默认内存池分配数组过大,容易导致栈溢出
上一篇随笔中提到了,rapidxml在每个xml对象中维护了一个内存池,自己管理变量的生存周期.看起来很好,但我们在实际使用中还是出现了问题. 项目中我们的模块很快写好了,在windows和linux ...
- 2017.11.21 查询某个字段为null的记录
注意,不使用 = null, 而是 is null. select fd_username, fd_tenantid, fd_validity from t_user WHERE fd_validit ...
- mongodb 踩坑记录
Map-Reduce Map-Reduce 是 mongodb 处理批量数据的大杀器,凡是数据量大并且定时处理能满足需求的,都可以试着扔给 mongodb,让它去 Map-Reduce. 以下截取自文 ...
- Solution of NumberOfDiscIntersections by Codility
question:https://codility.com/programmers/lessons/4 this question is seem like line intersections qu ...
- 火车票抢票API 根据乘客的车次与座席要求快速订票出票
火车票抢票API 根据乘客的车次与座席要求快速订票出票:https://www.juhe.cn/docs/api/id/257 1.站站查询 接口地址:http://v.juhe.cn/grabTic ...