http://blog.csdn.net/sloan6/article/details/9231337
基础知识
为了简单起见,只显示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
- int main()
- {
- int area_code,location_code;
- unsigned char c[3]={0};
- FILE * fp = fopen("gb2312_table.c","wb");
- char buf[100];
- if(fp)
- {
- sprintf(buf,"#include \"gb2312.h\"\n\nunsigned short gb2312_table[]=\n{\n");
- fwrite(buf,1,strlen(buf),fp);
- for(area_code=1;area_code<95;area_code++)
- {
- fputc('\t',fp);
- c[0]=area_code + 0xA0;
- for(location_code=1;location_code<95;location_code++)
- {
- c[1]=location_code+0xA0;
- if(area_code == 1 && location_code == 1)
- sprintf(buf," 0x%02X%02X",c[0],c[1]);
- else
- sprintf(buf,",0x%02X%02X",c[0],c[1]);
- fwrite(buf,1,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,1,strlen(buf),fp);
- fclose(fp);
- }
- return 0;
- }
这里多生成了一个函数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, const char *sIn, int iInLen)
- {
- 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) - 1)
- {
- perror("iconv_open()");
- return -1;
- }
- size_t iSrcLen=iInLen;
- ret = iconv(cd, &pIn,&iSrcLen, &pOut,&iLeftLen);
- if (ret == (size_t) - 1)
- {
- perror("iconv()");
- iconv_close(cd);
- return -1;
- }
- 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=0;i
- {
- if(gb2312[i]<128)
- {
- printf("ASCII Encode \t-- code:%c \n",gb2312[i]);
- }
- else
- {
- 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]);
- i++;
- }
- }
这个函数将GB2312编码字符串转换为UTF-16BE(大端字节序)字符串,转换后的每个字符用2Byte存储,高位在前低位在后
- static int Gb2312ToUtf16be(char *sOut, int iMaxOutLen, const char *sIn, int iInLen)
- {
- 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) - 1)
- {
- perror("iconv_open()");
- return -1;
- }
- size_t iSrcLen=iInLen;
- ret = iconv(cd, &pIn,&iSrcLen, &pOut,&iLeftLen);
- if (ret == (size_t) - 1)
- {
- perror("iconv()");
- iconv_close(cd);
- return -1;
- }
- 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
- #include "bmp_header.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 = 0;
- int w=0,h=0;
-
- fp = fopen(src_bmp24_file, "rb");
- if(fp)
- {
-
- #ifdef _WIN32
- BITMAPFILEHEADER bmpheader={0};
- BITMAPINFO bmpinfo={0};
- fread(&bmpheader,sizeof(BITMAPFILEHEADER),1,fp);
- fread(&bmpinfo.bmiHeader,sizeof(BITMAPINFOHEADER),1,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),1,fp);
- fread(&bmp_info,sizeof(Infohead),1,fp);
- w = bmp_info.biWidth;
- h = bmp_info.biHeight;
- data_size = bmp_head.bfSize - bmp_head.bfOffBits;
- #endif
- if(h<0)h=-h;
- if(data_size != w * h * 3)
- {
- printf("not 24 bit bmp,file size = %d,w=%d,h=%d\n",data_size,w,h);
- fclose(fp);
- return -1;
- }
- bmp_data = (uint8_t *)malloc(data_size);
- memset(bmp_data,0,data_size);
- if(bmp_data)
- {
- fread(bmp_data,data_size,1,fp);
- }
- fclose(fp);
- fp = NULL;
- }
- if(bmp_data)
- {
- pSwsCtx = sws_getContext(
- w,
- h,
- PIX_FMT_BGR24,
- w,
- h,
- PIX_FMT_YUV420P,
- SWS_POINT,
- NULL,
- NULL,
- NULL);
- if(pSwsCtx)
- {
- uint8_t *data[4]={bmp_data,NULL,NULL,NULL};
- int linesize[4] ={w*3,0,0,0};
- int height = 0;
- 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,0,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,
- 0,
- h,
- yuv_frame ->data,
- yuv_frame ->linesize);
- fp = fopen(dst_yuv_data_file,"w");
- if(fp)
- {
- char buf[1024]={0};
- int i=0;
- sprintf(buf,"/*********************Y***************************/\nunsigned char data_Y[]={");
- fwrite(buf,1,strlen(buf),fp);
- for(i=0;ilinesize[0]*height;i++)
- {
- if(!(i%16))
- {
- sprintf(buf,"\n\t");
- fwrite(buf,strlen(buf),1,fp);
- }
- if(i)
- {
- sprintf(buf,",0x%02X",*(yuv_frame ->data[0]+i));
- }
- else
- {
- sprintf(buf," 0x%02X",*(yuv_frame ->data[0]+i));
- }
- fwrite(buf,strlen(buf),1,fp);
- }
- sprintf(buf,"\n};\n//%d bytes\n/**************end of Y***************************/\n\n",yuv_frame ->linesize[0]*h);
- fwrite(buf,strlen(buf),1,fp);
- sprintf(buf,"/********************UV***************************/\nunsigned char data_UV[]={");
- fwrite(buf,1,strlen(buf),fp);
- for(i=0;ilinesize[1]*height/2;i++)
- {
- if(!(i%8))
- {
- sprintf(buf,"\n\t");
- fwrite(buf,strlen(buf),1,fp);
- }
- if(i)
- {
- sprintf(buf,",0x%02X,0x%02X",*(yuv_frame ->data[1]+i),*(yuv_frame ->data[2]+i));
- }
- else
- {
- sprintf(buf," 0x%02X,0x%02X",*(yuv_frame ->data[1]+i),*(yuv_frame ->data[2]+i));
- }
- fwrite(buf,strlen(buf),1,fp);
- }
- sprintf(buf,"\n};\n//%d bytes\n/*************end of UV***************************/\n\n",yuv_frame ->linesize[1]*h);
- fwrite(buf,strlen(buf),1,fp);
- fclose(fp);
- fp = NULL;
- }
- av_free(yuv_frame);
- av_free(buffer);
-
- sws_freeContext(pSwsCtx);
- pSwsCtx = NULL;
- }
- free(bmp_data);
- bmp_data = NULL;
- }
- return 0;
- }
其中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/9231373
经过上一篇的叙述,基本原理搞清楚后,便需要对我们在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*3;
- FILE *fp = fopen(filename,"wb");
- if(!fp)
- {
- perror("open file error");
- return -1;
- }
-
- bmp_head.bfType=0x4d42;
- bmp_head.bfSize=size+sizeof(FileHead)+sizeof(Infohead);
- bmp_head.bfReserved1=bmp_head.bfReserved2=0;
- bmp_head.bfOffBits=bmp_head.bfSize-size;
-
- bmp_info.biSize=40;
- bmp_info.biWidth=width;
- bmp_info.biHeight=-height;
- bmp_info.biPlanes=1;
- bmp_info.biBitCount = 24;
- bmp_info.biCompress=0;
- bmp_info.biSizeImage=size;
- bmp_info.biXPelsPerMeter=0;
- bmp_info.biYPelsPerMeter=0;
- bmp_info.biClrUsed=0;
- bmp_info.biClrImportant=0;
-
- fwrite(&bmp_head,1,sizeof(FileHead),fp);
- fwrite(&bmp_info,1,sizeof(Infohead),fp);
- fwrite(data,1,size,fp);
- fclose(fp);
- return 0;
- }
//转换函数,这里是一个区转换为一个图片
- 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 = 0;
- FT_Bitmap *ft_bmp;
-
- unsigned short unicode;
- int index=0;
- int area,location;
- char testfilename[100];
-
- unsigned char *image = NULL, *pimage;
- int temp;
-
- if(font_width <= 0 && font_height <= 0)
- {
- printf("invalidate font size.\n");
- return -1;
- }
- if(font_width <= 0)
- font_width = font_height;
- if(font_height <= 0)
- font_height = font_width;
- if(font_width % 2)
- {
- printf("invalidate font size.\n");
- return -1;
- }
- setlocale(LC_ALL,"zh_CN.UTF-8");
-
- do
- {
-
- error = FT_Init_FreeType(&library);
- if (error)
- {
- printf("can not init free type library!\n");
- break;
- }
-
- error = FT_New_Face(library, font_file, 0, &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 * 3);
- if(!bmpdata)
- {
- printf("outof memory.\n");
- break;
- }
- image = malloc(94 * font_width * font_height * 3);
- 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=0;inum_fixed_sizes;i++)
- {
- printf("supported size %d:width=%d,heigh=%d\n",i+1,face->available_sizes[i].width,face->available_sizes[i].height);
- }
- #endif
- error = FT_Select_Charmap(face,FT_ENCODING_UNICODE);
- if(error)
- {
- printf("select char map error.\n");
- break;
- }
-
- 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;
- }
-
-
- for(area = 0;area < 87;area ++)
- {
- if( (area >8 && area < 15)
- ||(area > 86 && area < 94)
- )
- {
- continue;
- }
- memset(image,0,94 * font_width * font_height * 3);
- pimage = image;
- for(location = 0;location < 94;location++)
- {
- index = area * 94 + location;
- if(Gb2312ToUnicode(gb2312_table[index],&unicode) < 0)
- {
- 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;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ft_bmp = &face->glyph->bitmap;
- #if 0
-
- 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/64,face->glyph->metrics.height/64,
- face->glyph->metrics.vertBearingX/64,face->glyph->metrics.vertBearingY/64,face->glyph->metrics.horiAdvance/64);
- }
- else
- {
- printf("HORI:(w:%ld h:%ld)(bearingX:%ld bearingY:%ld Advance:%ld)\n",face->glyph->metrics.width/64,face->glyph->metrics.height/64,
- face->glyph->metrics.horiBearingX/64,face->glyph->metrics.horiBearingY/64,face->glyph->metrics.vertAdvance/64);
- }
- 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:
- {
-
- int topblank = 0;
- int leftblank = 0;
- int rightblank = 0;
- int pitch = 0;
- 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/64;
- leftblank = font_width/2 + face->glyph->metrics.vertBearingX/64;
- }
- else
- {
- topblank = font_height * 2 /3 - face->glyph->metrics.horiBearingY/64;
- leftblank = face->glyph->metrics.horiBearingX/64;
- }
- if(topblank < 0)topblank = 0;
- if(leftblank < 0)leftblank = 0;
- rightblank = font_width - width - leftblank;
- if(rightblank < 0)rightblank = 0;
- pitch = ft_bmp ->width / 8;
- if(pitch% ft_bmp ->pitch)
- pitch = pitch + (ft_bmp ->pitch - pitch %ft_bmp ->pitch);
-
-
-
- printf("begin convert.area %d ----> %d\r",area,location);
- memset(bmpdata,0,font_width * font_height * 3);
- pdata = bmpdata;
- pdata += topblank *font_width * 3;
- for(i=0;i
- {
- pdata += leftblank * 3;
- k = 7;
- for(j=0;j
- {
- if(ft_bmp_buff[j/8] & (1 << k) )
- {
-
- pdata[1] = 255;
- pdata[2] = 255;
- }
- k--;
- if(k<0)k=7;
- pdata += 3;
- }
- ft_bmp_buff += pitch;
- pdata += rightblank * 3;
- }
-
-
-
-
-
-
-
-
-
-
- }
- break;
- default:
- printf("位图为非单色图片.\n");
- goto done;
- break;
- }
- pdata = bmpdata;
- pimage = image + location * font_width * 3;
- for(temp=0;temp
- {
- memcpy(pimage,pdata,font_width * 3);
- pdata += font_width * 3;
- pimage += 94 * font_width *3;
- }
- #ifndef _WIN32
- usleep(10);
- #else
- Sleep(10);
- #endif
- }
-
- sprintf(testfilename,"./testbmp/area%d_%dx%d.bmp",area,font_width,font_height);
-
- if(save_bmp24(testfilename,94 * font_width,font_height,image))
- {
- printf("save bmp file [%s] error.\n",testfilename);
- }
- }
- printf("\nConvert Done.\n");
-
- }while (0);
- 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 0;
- }
这里上传几个程序转换的图片:
14x16:
16x18:
20x24:
28x32:
将编码转换为图片后,需要将bmp24图片数据转换为yuv420p数据,利用libswscale库进行转换的核心代码已经在上一篇贴了,这里不再重贴.
下面是转换后的结果,当然也可以直接将数据保存为一个二进制文件,而不是一个C源程序文件
-
- 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
- };
-
-
-
-
- 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
- };
-
-
实战
http://blog.csdn.net/sloan6/article/details/9231413
通过数据准备篇,将数据准备好后,其实剩下的工作已经很简单了,通过以下几个步骤即可把一个中文显示在OSD画面上:
1. 使用SWOSD_setBmpchangeWinXYPrm函数设置好OSD显示坐标位置;
2. 设置SWOSD_Hndl句柄中SWOSD_BmpWinPrm类型成员数组中对应的窗口的width,height,lineOffset对应的值,width是OSD窗口宽度,如果yuv数据来自的是32x32的bmp图片,则width=n*32,其中n为字符个数,height为OSD窗口高度,lineOffset为每个扫描行Y数据所占字节数;
3. 通过SWOSD_setBmpWinAddr函数设置对应窗口的Y数据和UV数据地址.
注:1、2中如果某些值设置不对,会提示以下错误:
SWOSD_winDraw():baseI fail or baseJ fail xxx xxx for window id xxx
下面是两个测试图片: