思路
我们最终的目的是实现字母或文字叠加到 YUV图片中,在之前几篇文章中,我们已经熟悉并实现了对YUV图片的操作。所以接下来就是字模的认识并叠加到YUV图片中。首先,我们先从最简单的开始—在终端打印ASCII字模
在操作之前,需要先去了解下 字符编码的来源与组成。
ASCII 是最初也是最简单的字库,由 7bit 表示,也就是0-127,存储着128个字模.如图
我们只需 使用点阵生成工具 设置好 表示一个字模的 长宽之后,保存字库。我们就可以得到存储 96 个字模的字库(注:因为ASCII码中前32个字符为控制字符不显示)。每个字符 由 长宽 bit 组成,如图(图为 2448):
将字库保存为 .bin 文件存入 linux 中。这个字库就相当于一个字典。每一页存着一个字符,所以我们要想找到某个字符,只要翻到那一页就好了。每个字符 在ASCII码中位置是固定的。在 Linux 中,使用命令:
hexdump -x ascii.bin
就可以查看字库信息,如图(* 号代表中间全为 0):
即我们要想从字库中拿一个字模,找到偏移量 拿 48*24 bit 就可以了。
偏移量 = 一个字模字节数 X (字模ASCII码 - 0x20)
代码:
size = (int)pString[num];
offset = LUX_oneLetter_size*( size - 0x20 );
int LUV_GetCharacter(int offset)
{
int nRet = 0;
int Offset = 0;
FILE *readFp = NULL;
FILE *writeFp = NULL;
char *output = NULL;
char *readAddr = NULL;
char *writeAddr = NULL;
readAddr = (char *)malloc(LUX_allFile_size * LUX_oneLetter_size);
writeAddr = (char *)malloc(LUX_oneLetter_size);
output = writeAddr;
readFp = fopen(LUX_ALL_Font,"rb+");
if (readFp == NULL)
{
printf("fopen LUX_ALL_Font fail\n");
return -1;
}
writeFp = fopen(LUX_one_Font,"wb+");
if (writeFp == NULL)
{
printf("fopen LUX_one_Font fail\n");
return -2;
}
nRet = fread(readAddr,1,LUX_allFile_size * LUX_oneLetter_size,readFp);
if(nRet == 0)
{
printf("read fail\n");
return -3;
}
output = readAddr + offset;
nRet = fwrite(output,1,LUX_oneLetter_size,writeFp);
if(nRet == 0)
{
printf("fwrite fail\n");
return -4;
}
free(readAddr);
free(writeAddr);
fclose(readFp);
fclose(writeFp);
return 0;
}
依照上面操作,就能从字库中拿出一个字模。如图:
可以看出,上面字模是 16 进制表示的。我们就把他当成 2 进制来看就好了。在24*48 bit中有显示就为1 无显示就为 0;所以我们用循环去遍历 Letter.bin文件。1 就打印 * 号,0 就打印空格。就能显示字模了。代码:
int LUX_check_Letter(int offsize ,char *backGroun)
{
int bit = 0;
int width = 0;
int bety = 0;
int higth = 0;
char buf[144] = {0};
const int oneBit = 8;
FILE *fileAddr = NULL;
fileAddr = fopen(LUX_one_file,"rb+");
fread(buf,1,LUX_oneLetter_size,fileAddr);
for(bety = 0 ;bety < LUX_oneLetter_size ;bety++)
{
if(bety%LUX_oneLine_bety == 0)
{
printf("\n");
}
for(bit = 0 ;bit < oneBit ;bit++)
{
if (buf[bety] & (0x80 >> bit))
{
printf("*");
}
else
printf(" ");
}
}
fclose(fileAddr);
}
最终实现图
需要注意的是 因为设定的字模大小为 24*48 的。所以一行是 3 个byte。即遍历完 3个byte 之后,需要换行(其他大小都需考虑这个问题)。