点阵放大算法

点阵纵向取模以及放大算法


http://blog.csdn.net/sddsighhz/article/details/39290703


这两天在调打印,在网上找各种提取字模相关的算法,但是一般字模取出来后的数据都是横向的,在打印字上打出来旋转了90°,没办法,只好转换一下了。

先说一下取字模数据的算法(本人C写的不多,只能算初级,见笑了):


下面一段摘自网上:

  HZK16字库是符合GB2312标准的16×16点阵字库,HZK16的GB2312-80支持的汉字有6763个,符号682个. 
  其中一级汉字有 3755个,按声序排列,二级汉字有3008个,按偏旁部首排列. 
  我们在一些应用场合根本用不到这么多汉字字模, 所以在应用时就可以只提取部分字体作为己用.
  HZK16字库里的16×16汉字一共需要256个点来显示, 也就是说需要32个字节才能达到显示一个普通汉字的目的.
  我们知道一个GB2312汉字是由两个字节编码的,范围为0xA1A1~0xFEFE. 
  A1-A9为符号区, B0到F7为汉字区. 每一个区有94个字符(注意:这只是编码的许可范围,不一定都有字型对应,比如符号区就有很多编码空白区域).
  下面以汉字""为例, 介绍如何在HZK16文件中找到它对应的32个字节的字模数据.
  前面说到一个汉字占两个字节,这两个中前一个字节为该汉字的区号,后一个字节为该字的位号.
  其中, 每个区记录94个汉字, 位号为该字在该区中的位置. 所以要找到""在hzk16库中的位置就必须得到它的区码和位码.
  区码:汉字的第一个字节-0xA0 (因为汉字编码是从0xA0区开始的, 所以文件最前面就是从0xA0区开始, 要算出相对区码)
  位码:汉字的第二个字节-0xA0
  这样我们就可以得到汉字在HZK16中的绝对偏移位置:
      offset=(94*(区码-1)+(位码-1))*32
    
    注解:
     1.区码减1是因为数组是以0为开始而区号位号是以1为开始的
      2.(94*(区号-1)+位号-1)是一个汉字字模占用的字节数
      3.最后乘以32是因为汉字库文应从该位置起的32字节信息记录该字的字模信息(前面提到一个汉字要有32个字节显示)

//--------------汉字字模的数据结构----------------//

[cpp]  view plain  copy
  1. typedef struct typFNT_GB16  
  2. {  
  3.       signed char Index[2];  //汉字内码索引  
  4.       char Msk[32];    //点阵码数据  
  5. }  

[cpp]  view plain  copy
  1. void getCharLattice(char (*prt),char *buffer)  
  2. {  
  3.     int fh;  
  4.     long pos;               /* Position of file pointer */  
  5.     long location;  
  6.     long qh,wh;  
  7.   
  8.     fh = open( "/usr/lib/X11/fonts/HZK16", O_RDONLY );  
  9.   
  10.     // 汉字的区号  
  11.     qh=prt[0]-0xa0;  
  12.     // 汉字的位号  
  13.     wh=prt[1]-0xa0;  
  14.   
  15.     // location=(94*(qh-1)+(wh-1))*一个点阵字模的字节数。  
  16.     location=(94*(qh-1)+(wh-1))*32;  
  17.   
  18.     // 移动指针到location  
  19.     pos = lseek( fh, location, SEEK_SET);  
  20.   
  21.     // 读数据  
  22.     read( fh, buffer, 32);  
  23.   
  24.     char tmp[16][2];  
  25.     memcpy(tmp,buffer,32);  
  26.     transverse_modulus(tmp,buffer);  
  27.   
  28.     close( fh );  
  29. }  
字库中的字模数据是横向取模左高位,数据排列:从左到右、从上到下。
 

我这边用作打印需要纵向取模,下面是我自己写的一个转换算法。聊以备忘

[cpp]  view plain  copy
  1. char shift_value(char org,int index)  
  2. {  
  3.     org = (org & (0x1 << index)) >> index;  
  4.     return org;  
  5. }     
  6.   
  7. void transverse_modulus(char org[16][2],char *re)  
  8. {  
  9.     char tmp[2][16];  
  10.     int j=0,n=0,column = 0;  
  11.     for(;j<2;j++)  
  12.     {  
  13.         int i=0,index = 0;  
  14.         for(;i<16;i++)  
  15.         {  
  16.             if(i%2 != 0)  
  17.             {  
  18.                 n = 1;  
  19.             }  
  20.             else  
  21.             {  
  22.                 n = 0;  
  23.             }  
  24.             tmp[j][i] = (shift_value(org[(1-n)*8][column],7-index)<<0) | \  
  25.                         (shift_value(org[(1-n)*8+1][column],7-index)<<1) | \  
  26.                         (shift_value(org[(1-n)*8+2][column],7-index)<<2) | \  
  27.                         (shift_value(org[(1-n)*8+3][column],7-index)<<3) | \  
  28.                         (shift_value(org[(1-n)*8+4][column],7-index)<<4) | \  
  29.                         (shift_value(org[(1-n)*8+5][column],7-index)<<5) | \  
  30.                         (shift_value(org[(1-n)*8+6][column],7-index)<<6) | \  
  31.                         (shift_value(org[(1-n)*8+7][column],7-index)<<7);  
  32.             if(i%2 != 0)  
  33.                 index ++;  
  34.         }  
  35.         column++;  
  36.     }  
  37.   
  38.     memcpy(re,tmp,32);  
  39. }  
因为16*16打印出来字体很小,所以放大成32*32。下面也是自己写的一个放大函数

[cpp]  view plain  copy
  1. void zoom8(char font8,char *date)  
  2. {  
  3.     int m=0,n=0;  
  4.     char high,low;  
  5.     high = (font8 & 0xf0) >> 4;  
  6.     low  = (font8 & 0x0f);  
  7.     char tmp[2];  
  8.     memset(tmp,0,2);  
  9.   
  10.     int j=0;  
  11.     for(;m<4;m++)  
  12.     {  
  13.         if((high >> m) & 0x1)  
  14.         {  
  15.             tmp[0] |= (1 << j);  
  16.             tmp[0] |= (1 << (j+1));  
  17.         }  
  18.         else  
  19.         {  
  20.             tmp[0] &= (~(1 << j));  
  21.             tmp[0] &= (~(1 << (j+1)));  
  22.         }  
  23.         j += 2;  
  24.     }  
  25.   
  26.     j=0;  
  27.     for(;n<4;n++)  
  28.     {  
  29.         if((low >> n) & 0x1)  
  30.         {  
  31.             tmp[1] |= (1 << j);  
  32.             tmp[1] |= (1 << (j+1));  
  33.         }  
  34.         else  
  35.         {  
  36.             tmp[1] &= ~(1 << j);  
  37.             tmp[1] &= ~(1 << (j+1));  
  38.         }  
  39.         j += 2;  
  40.     }  
  41.   
  42.     memcpy(date,tmp,2);  
  43. }  
  44. //将16*16的数组转换后拷贝到font32中  
  45. void zoom16_to_font32(char *font16,char *font32)  
  46. {  
  47.     char zoomout[32][4];  
  48.     char zoom[2];  
  49.     int j=0,i=0,t;  
  50.     for(;j<32;j++)  
  51.     {  
  52.         int n = j%2;  
  53.         zoom8(font16[j],zoom);  
  54.         memcpy(zoomout[i]+n*2,zoom ,2);  
  55.         if(n != 0)  
  56.         {  
  57.             memcpy(zoomout[i+1],zoomout[i],4);  
  58.             i += 2;  
  59.         }  
  60.     }  
  61.   
  62.     memcpy(font32,zoomout,128);  
  63. }  

这个放大的原理是将16*16的点阵,当作32*32的,那么就相当于原来的一个点变成了4个点。上面的代码是将一行2个字节变成了2行4个字节,这样放大后的打印效果就比16*16的好很多了。

但是我这里还有一个问题,就是字母和数字等字符应该如何去提取字模呢?汉字是2个字节,但是字符只有一个字节,在字库中的位置应该如何计算呢?

HZK16读取英文数字等字符还没找到解决方法,不过有人给了一个解决方法,就是字符用ASC16字库来获取点阵数据,我试过,是可以实现的。至于读取方式需要修改前面的读取代码

[cpp]  view plain  copy
  1. void getCharLattice(char (*prt),char *buffer)  
  2. {  
  3.     int fh;  
  4.     long pos;               /* Position of file pointer */  
  5.     long location;  
  6.     long qh,wh;  
  7.   
  8.     if(prt[1] & 0xff)  
  9.     {  
  10.         fh = open( "/usr/lib/X11/fonts/HZK16", O_RDONLY );  
  11.   
  12.         // 汉字的区号  
  13.         qh=prt[0]-0xa0;  
  14.         // 汉字的位号  
  15.         wh=prt[1]-0xa0;  
  16.   
  17.         // location=(94*(qh-1)+(wh-1))*一个点阵字模的字节数。  
  18.         location=(94*(qh-1)+(wh-1))*32;  
  19.   
  20.         // 移动指针到location  
  21.         pos = lseek( fh, location, SEEK_SET);  
  22.   
  23.         // 读数据  
  24.         read( fh, buffer, 32);  
  25.   
  26.         char tmp[16][2];  
  27.         memcpy(tmp,buffer,32);  
  28.         transverse_modulus32(tmp,buffer);  
  29.     }  
  30.     else  
  31.     {  
  32.         ((fh=open("/usr/lib/X11/fonts/ASC16",O_RDONLY))< 0) {  
  33.             printf("Can not open ASC16\r\n");  
  34.         }  
  35.             location=prt[0]*16;  
  36.             lseek(fh,location,SEEK_SET);  
  37.             read(fh,buffer,16);  
  38.   
  39.         char tmp[32];  
  40.         memcpy(tmp,buffer,16);  
  41.   
  42.         transverse_modulus16(tmp,buffer);  
  43.     }  
  44.   
  45.     close( fh );  
  46. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值