如何利用windows自带的矢量字库提取字模

如何利用windows自带的矢量字库提取字模,第1张

1  字体设置

首先需要设置字体。Win32 SDK提供了用于字体选择的通用对话框,只需调用ChooseFont函数,其返回值为一个布尔值。具体定义为BOOL ChooseFont(LPCHOOSEFONT lpcf)。调用此函数后,d出字体选择对话框,在此可以选择所需要的字体、字形、大小等参数。选择完毕后,如果点击了字体选择对话框上的确定键,此函数返回一个非零值;若点击的是取消键,则函数返回一个零值。调用此函数前,还要定义二个变量:

CHOOSEFONT  cf;

LOGFONT   logfont

CHOOSEFONT是有十多个字段的结构体,包含了ChooseFont函数用来初始化字体选择对话框的各种信息。LOGFONT也是一个结构体,包含14个字段,定义了字体的各种属性。当点击确定键后,系统通过LOGFONT结构返回选定的字体信息。返回的字体信息保存在CHOOSEFONT结构的lpLogFont字段指定的LOGFONT结构中。

下面是调用ChooseFont函数的代码:

 

 //初始化CHOOSEFONT

cf.lStructSize  =sizeof (CHOOSEFONT);

cf.hwndOwner  =hwnd;  //当前窗口的句柄

cf.hDC   =NULL;

cf.lpLogFont  =&logfont;//系统返回的字体信息保存在此处

cf.iPointSize  =0;

cf.Flags   =CF_INITTOLOGFONTSTRUCT|CF_

SCREENFONTS|CF_EFFECTS;

cf.rgbColors  =0;

cf.lCustData  =0;

cf.lpfnHook  =NULL;

cf.lpTemplateName =NULL;

cf.hInstance  =NULL;

cf.lpszStyle  =NULL;

cf.nFontType  =0;

cf.nSizeMin  =0;

cf.nSizeMax  =0;

ChooseFont(&cf); //此函数调用后d出字体选择通用对话框

如果ChooseFont(&cf)函数返回非零值,则字体已经选定。选定的字体就保存在logfont变量中。接下来要做的就是创建选定的逻辑字体。可以调用CreateFontIndirect函数创建逻辑字体。CreateFontIndirect函数接受一个指向LOGFONT结构的指针,具体定义为HFONT CreateFontIndirect(CONST LOGFONT?鄢lplf)。代码如下:

HFONT hNewFont=CreateFontIndirect(&logfont);

至此字体创建就完成了。直接调用SeletObject函数就可以将创建的逻辑字体选入设备描述表。在位图转换里将使用SelectObject函数将hNewFont选入内存设备描述表。但还要注意一点,在程序结束前,必须调用DeleteObject(hNewFont)函数来释放字体句柄,避免内存泄漏。下面介绍文本转换为位图的具体实现过程。

2  位图转换

此处以提取一个“婷”字的字模为例进行说明。首先需要定义如下变量:

static WCHAR        Hanzi[]=“婷”;

static HBITMAP      hBitmap;

static int          cxBitmap,cyBitmap;

static HDC                      hdc,hdcMem;

PAINTSTRUCT              ps;

SIZE    size;

cxBitmap、cyBitmap是所要创建的位图的大小,二者与GetTextExtentPoint32函数得到的文本大小一致,在此处即是“婷”字的大小。

以下是将汉字文本转化为位图的具体方法,一般在WM_PAINT消息中处理。

case WM_PAINT:

hdc=BeginPaint(hwnd,&ps);//得到当前窗口的设备句柄

hdcMem=CreateCompatileDC(hdc);//创建一个内存设备描述表

SelectObject(hdcMem,hNewFont);//将创建的字体选入内存设备描述表

GetTextExtendPoint32W(hdcMem,Hanzi,1,&size);

 //获取要显示的文本的大小

cxBitmap  =size.cx.;

cyBitmap  =size.cy;

hBitmap  =CreateCompatileBitmap(hdc,cxBitmap,

cyBitmap); //创建一个位图句柄

SelectObject(hdcMem, hbitmap);//将位图选进内存设备描述表

TextOutW(hdcMem,0,0,Hanzi,1);//将汉字画在内存设备描述表的位图上

BitBlt(hdc,0,0,cxBitmap,cyBitmap,hdcMem,0,0,SRC-

                 COPY);                         //将位图显示在窗口的客户区,用来观察显示的效果

至此,汉字的点阵化过程就完成了,接下来就应该提取字模。

3  提取字模

提取字模要用到的是GetPixel函数,定义为COLORREF GetPixel(HDC hdc,int nXPos,int nYPos)。此函数返回一个COLORREF类型的值,即nXPos、nYPos所指定的点的RGB值。位图的大小在前文已经确定,在此范围类将每个象素点扫描一次,根据返回的RGB值生成点阵码。因为Windows矢量字体有灰度等级,所以必须选择合适的RGB值,用来判断此点是否有效。白色的RGB值是FFFFFFH,深灰的是808080H,黑色的是000000H。可以选择深灰做为判断依据,当函数返回值小于808080H时,认为此点有效。下面是提取字模的函数,以字节为存储单位,从第一行第一个点开始扫描:

static Zimo[2048];//点阵码存在此数组中

void GetZimo(HDC hdc,int nXPos,int nYPos)

{

   int Hang,Lie;  //Hang为扫描的行数

   int temp,i,j,g;

   Hang=nYPos;

   Lie=nXPos;

   if(Lie % 8==0 ){

    Lie=Lie/8; //位图的宽度是8的整数倍,所以

 //只需要Lie/8个字节来存储字模

                   Temp=0;

 }

    else{

                             temp=Lie % 8;

 Lie=Lie/8+1;//位图的宽度不是8的整数倍,

  //所以只需要Lie/8+1个字节来存储字模

  }

  memset(Zimo,0,2048);//将字模数组全置0

  for(i=0;i<Hang;i++){

    for(j=0;j<Lie;j++){

    if( (temp!=0) && (j==Lie-1) ){

      for(k=0;k<temp;k++){

       g=(int)GetPixel(hdc,j*8+k,i);

       if(g<0x00808080)

        Zimo[i*Lie+j]+=(unsigned 

 char)pow(2,7-k);

                              }

                             }

                             else{

                                      for(k=0;k<8;k++){

                                       g=(int)GetPixel(hdc,j*8+k,i);

                                    if(g<0x00808080)

                                      Zimo[i*Lie+j]+=(unsigned char)pow(2,7-k);

     }

    }

    }

   }

}

在WM_PAINT消息中,调用GetZimo(hdcMem,cxBit-

map,cyBitmap)即可得到汉字的字模。在程序的最后,还必须做些扫尾的工作:

DeleteObject(hBitmap);//使用完后必须释放设备描述

//表和位图句柄,避免内存泄漏

DeleteObject(hNewFont);

DeleteDC(hdcMem);

EndPaint(hwnd,&ps);

Return 0; //WM_PAINT消息处理完后返回

4  输出结果

以“婷”字为例,d出字体选择对话框后,字体选新宋体、字形选常规、字号选小二。得出Hang=24,Lie=3,存储72个字节。字模为

00H,00H,00H,00H,00H,00H,06H,03H,00H,04H,01H,80H,04H,01H,0CH,04H,3EH,F0H,0CH,00H,00H,7FH,CFH,F8H,08H,88H,10H,08H,88H,10H,18H,8FH,F0H,10H,90H,04H,11H,BFH,FEH,11H,20H,04H,31H,60H,08H,21H,40H,18H,1FH,0FH,E0H,03H,01H,80H,05H,C1H,80H,0CH,C1H,80H,08H,01H,80H,10H,0DH,80H,20H,03H,00H,00H,00H,00H。

在纸上画出点阵码,正好是“婷”字,如图1所示。从cxBitmap和cyBitmap可以知道,“婷”字点阵大小是24×24。

提取到的字模这样导入程序:

1、新建一个文本档,在电脑的记事本中即可找到新建文档。

2、用notepad打开文档将生成的字模粘贴进去即可,这样字模就导入到程序了。


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/12022475.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-20
下一篇 2023-05-20

发表评论

登录后才能评论

评论列表(0条)

保存