作者:wangxinus, <wangxinus@gmail.com>
来源: http://wangxinus.cublog.cn
一、关于字模提取的方式。
制作字模提取工具的原理,其实方法都大同小异。就我所查阅的资料来看,提取字模主要有以下几种方法:
1、从字模库中直接提取。该方法受限于字模库,比如你需要16*16的字模和20*20的字模,你就必须去找到这2个字模库。
2、从ttf库中直接提取。该方法提取出来的字模很光滑,效果很好。同样你需要一个ttf库,它是矢量的,可以支持不同的大小。
3、在内存的位图上画出文字,然后生成字模。该方法写出来的程序不需要额外的字库文件,依赖于操作系统中的字体。但是一般操作系统中都带有大量的字体,足够我们使用,还可以很自由的选择自己喜欢的字体、大小等等。所以我决定使用第3种方法来制作工具。
二、关于Qt4.5。
采用Qt4.5来制作该工具的最主要的原因是它可以编写跨平台的代码,其次是我正在学习Qt,学以致用才是王道。另外Qt内部全采用unicode的编码,且提供了其他编码转unicode的良好支持,它同样提供了非常方便的设备上下文的绘图操作,可以方便的完成文字在内存中的绘制和提取字模的工作。
三、关于网上的同类软件。
目前在网上能搜到很多字模提取的工具和方法,大部分都介绍如何从中文的字模库中提取出字模用于嵌入式设备上LCD屏的显示。其次大多工具都是基于VC开发,无法做到跨平台且基本上都没有开放源代码,有时候需要定制生成字库的文件格式,只有自己实现。
四、关于一些技术细节。
1、Qt的绘图操作。
Qt绘图使用的类是QPainter,使用该类在QWidget上绘图时,需要重载
void QWidget::paintEvent ( QPaintEvent * event ) [virtual protected]
并在此函数中进行绘图操作,在其他地方使用QPainter直接对QWidgets绘图会出现错误:
QPainter::begin: Widget painting can only begin as a result of a paintEvent
如果不是直接对QWidget绘图,而是在内存中建立一个位图,选入设备,然后在位图上绘图,则没有该限制。
2、Qt的图片类。
Qt中四种处理图像数据的类: QImage,QPixmap,QBitmap,QPicture。关于它们的作用和区别,参考 这里 。
3、使用QImage绘制文字并提取字模
建立一个QImage对象,选入绘图设备中,并在上面绘制文字,伪代码如下
QImage image( int width, int height, Format format );
QPainter painter(&image);
painter.drawText(image.rect(), QString(QChar(ushort unicode)));
(1)QImage对象初始化。
图像的宽、高,若是要生成16*16的点阵字模,就把宽、高设置为16。format是图像的存储格式,支持的格式有RGB, RGBA等多种模式。由于我们生成的字模不用记录颜色,有1bit来表示1个像素的有无即可。QImage提供了这样的格式,QImage::Format_Mono 和 QImage::Format_MonoLSB。它们都是用1bit来保存每个像素点,这样 1 byte 就可以保存8个像素点。它们的区别在于在 1 byte中的保存像素的高低位顺序。
QImage::Format_Mono中 [0 1 2 3 4 5 6 7]8个点保存到 byte中为 H -> L, 即第1像素保存在最高位;
QImage::Format_MonoLSB中 [0 1 2 3 4 5 6 7]8个点保存到 byte中为 L -> H, 即第1像素保存在最低位。
(2)QImage对象存储数据的获取。
const uchar * QImage::scanLine ( int i ) const 函数可以获取扫描一行的数据,
const uchar * QImage::bits () const 函数获取所有的数据。
需要说明的是, 每一行的数据都是按照4bytes对齐的。 16*16的字模, 一行的数据不是2bytes, 而是4bytes, 我们可以只把用到的2bytes单独提取出来。
文章出处:DIY部落(http://www.diybl.com/course/3_program/c++/cppjs/20091006/178104.html)