图像叠加文字(点阵字库)原理解析

1、简述

本文主要是为了说明如何利用点阵字库实现在图像上叠加文字的原理,点阵字库相对矢量字库存在放大的时候锯齿明显、不平滑的缺点,但是较为容易理解使用,因此此处先说明点阵字库文字叠加的使用原理,后续会分享利用矢量字库叠加文字。

针对矢量字库的运行我实现了一个demo,运行环境是vs+qt,代码量很少,可以直接运行AddTextToVideo.exe看效果。
demo上传了码云版本库,链接如下
(https://gitee.com/itcastcjh/video-exercise.git)

2.图像文字叠加解析

2.1.总体流程简述

流程上没有过于复杂的难以理解,想要实现点阵字库中解析数据并转换为图像的关键,是需要理解:点阵字库、机内码、区位码,总体流程图如下所示。
在这里插入图片描述

2.2.字库解析必备基础知识

2.2.1.点阵字库

点阵字库就是按照一定规律进行存储的字模的集合,存在制作好的多种字体和大小的字库(例如:HZK12、HZK16、HZK24,HZK32和HZK48字库及黑体、楷体和隶书字库),但是字库的汉字存储顺序都是根据区位码(下文详解)的规律进行排序存储的。
Demo中使用的HZK16点阵字库,因此下文的讲述均是针对1616的字体。HZK16是每一个汉字在纵、横各16点的区域内显示的,最小的单位是:位(bit),因此1616的汉字大小实际在字库中需要存储空间是16*16/8=32个字节。位为1表示有效的笔画,为0表示不在汉字组成的笔画范围内,字库中每个汉字的存储空间的大小影响字库中存储的数据位置的实际偏移值。

因为HZK12有些特殊,因此此处追加特别说明。因为12不便于数据的存取计算,所以实际制作中横向位数是8的倍数,即实际描述一个字体的点阵需要的存储空间是16*12/8=24个字节(一个字节8位,12位不足两个字节,如果不做对齐,那么取出数据的时候就不能直接整字节运用,需要增加偏移的考虑)。

2.2.2.区位码

国家标准将汉字和图形符号排列在一个94行94列的二维代码表中,一行代表一个分区即共有94个分区,一个分区94列即94个字符(有预留位,即没有定义字符),每两个字节分别用两位十进制编码,前字节的编码称为区码,后字节的编码称为位码,此即区位码。码表链接:http://www.sucaijishi.com/worth-62-416-1.html。

例如下图是上述链接表格中的部分截图,当前用表中的“啊”进行分析,最左侧的B0A0是当前一行中字符的机内码的起始值(十六进制),则“啊”的机内码为B0A1(下文会针对区位码到机内码转换的计算进行详解,此处不理解可忽略)。汉字“啊”在表中属于第16区,第1位,用十进制表示就是1601D(D表示当前是十进制表示的数据),它的前两位叫做区码,后两位叫做位码。

在这里插入图片描述

2.2.3.汉字国标码

定义每个汉字有一个全国统一代码的国家标准,每个汉字有个二进制编码,叫汉字国标码。 在我国汉字代码标准GB2312-80中有6763个常用汉字规定了二进制编码。
国标码并不等于区位码,它是由区位码稍作转换得到,其转换方法为:先将十进制区码和位码转换为十六进制的区码和位码,这样就得了一个与国标码有一个相对位置差的代码,再将这个代码的第一个字节和第二个字节分别加上20H即加上十进制的32D(H表示当前是十六进制表示的数据),就得到国标码。

例如:区位码中得出汉字“啊”的四位十进制表示的区位码是1601D,转为十六进制就是1001H,两个字节分别加上20H为3021H,则汉字“啊”的区位码为3021H。

2.2.4.机内码

汉字机内码,又称“汉字ASCII码”,简称“内码”,指计算机内部存储,处理加工和传输汉字时所用的由0和1符号组成的代码。汉字机内码是汉字最基本的编码,不管是什么汉字系统和汉字输入方法,输入的汉字外码到机器内部都要转换成机内码,才能被存储和进行各种处理。

由于国标码的与ASCII码一起使用存在二义性(例如“保”的国标码是3123H,而西文字符“1”和“#”的ASCII也为31H和23H,这个时候不知道是解析为“保”,还是解析为“1”和“#”)。因此汉字机内码是在国标码的基础上做出变形,因为ASCII最大是127,国编码的最高位一定为0,因为最大94分区和94个字符,即最大为5E,因此在国编码的最高位是0,为了区别ASCII,因此汉字机内码为国标码两个字节最高位置为1,即加上128D,十六进制即加上80H。

例如“啊”的国编码是3021H,两个字节个加上80H转换为机内码就是B0A1H。

2.2.5.必备基础知识总结

从上述流程介绍以及计算举例得出:
如果用char hz[2]来表示一个汉字,那么我可以计算出这个汉字的区位码为:
区码 = hz[0] - 128 - 32 = hz[0] - 160
位码 = hz[1] - 128 - 32 = hz[1] - 160

上述机内码叙述中说过,计算机内部的存储以及处理都是按照机内码进行处理的,下图是汉字“啊”对应的机内码输出结果得以验证。
在这里插入图片描述

2.3.点阵字库解析以及图像生成

2.3.1.提取字库文字点集

汉字在字库中存储的位置有区位码和字库的文字大小(按照16*16计算)决定,计算公式如下:

点阵字库的汉字的起始偏移地址 = (( 区码 - 1 ) * 94 + (位码 - 1) ) * 16 * 16 / 8;
(区码和位码减1是因为,编码表中的横纵起始值均为1,计算偏移值时,第一个值不存在偏移,故减1)

2.3.2.点阵集合使用

计算得到汉字在点阵字库中的起始地址后,根据字库文字大小提取数据,1616的字库一个汉字的点集是32个字节,然后构建二维数据,每2个字节(16个位)占一行,共计16行,就形成了1616的二维数据结构,如下图所示,图中每一个空格表示一个bit(位),一行16bit,点阵字库中构成笔画的位值为1,否则为0,实际使用中根据位判断,将与值为1的图像像素点赋予指定的颜色值构成图像数据,此处不进行yuv数据的构造讲解,文件简述中给出的demo链接是存在相关实现的。
在这里插入图片描述

2.4.运行效果展示

在这里插入图片描述

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

echo<£>

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值