我是靠谱客的博主 温婉狗,最近开发中收集的这篇文章主要介绍点阵纵向取模以及放大算法,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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

下面一段摘自网上:

 

  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个字节显示)

 

 

 

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

 

typedef struct typFNT_GB16
{
signed char Index[2];
//汉字内码索引
char Msk[32];
//点阵码数据
}

 

 

 

 

void getCharLattice(char (*prt),char *buffer)
{
int fh;
long pos;
/* Position of file pointer */
long location;
long qh,wh;
fh = open( "/usr/lib/X11/fonts/HZK16", O_RDONLY );
// 汉字的区号
qh=prt[0]-0xa0;
// 汉字的位号
wh=prt[1]-0xa0;
// location=(94*(qh-1)+(wh-1))*一个点阵字模的字节数。
location=(94*(qh-1)+(wh-1))*32;
// 移动指针到location
pos = lseek( fh, location, SEEK_SET);
// 读数据
read( fh, buffer, 32);
char tmp[16][2];
memcpy(tmp,buffer,32);
transverse_modulus(tmp,buffer);
close( fh );
}

字库中的字模数据是横向取模左高位,数据排列:从左到右、从上到下。

 

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

 

char shift_value(char org,int index)
{
org = (org & (0x1 << index)) >> index;
return org;
}
void transverse_modulus(char org[16][2],char *re)
{
char tmp[2][16];
int j=0,n=0,column = 0;
for(;j<2;j++)
{
int i=0,index = 0;
for(;i<16;i++)
{
if(i%2 != 0)
{
n = 1;
}
else
{
n = 0;
}
tmp[j][i] = (shift_value(org[(1-n)*8][column],7-index)<<0) | 
(shift_value(org[(1-n)*8+1][column],7-index)<<1) | 
(shift_value(org[(1-n)*8+2][column],7-index)<<2) | 
(shift_value(org[(1-n)*8+3][column],7-index)<<3) | 
(shift_value(org[(1-n)*8+4][column],7-index)<<4) | 
(shift_value(org[(1-n)*8+5][column],7-index)<<5) | 
(shift_value(org[(1-n)*8+6][column],7-index)<<6) | 
(shift_value(org[(1-n)*8+7][column],7-index)<<7);
if(i%2 != 0)
index ++;
}
column++;
}
memcpy(re,tmp,32);
}

因为16*16打印出来字体很小,所以放大成32*32。下面也是自己写的一个放大函数

 

void zoom8(char font8,char *date)
{
int m=0,n=0;
char high,low;
high = (font8 & 0xf0) >> 4;
low
= (font8 & 0x0f);
char tmp[2];
memset(tmp,0,2);
int j=0;
for(;m<4;m++)
{
if((high >> m) & 0x1)
{
tmp[0] |= (1 << j);
tmp[0] |= (1 << (j+1));
}
else
{
tmp[0] &= (~(1 << j));
tmp[0] &= (~(1 << (j+1)));
}
j += 2;
}
j=0;
for(;n<4;n++)
{
if((low >> n) & 0x1)
{
tmp[1] |= (1 << j);
tmp[1] |= (1 << (j+1));
}
else
{
tmp[1] &= ~(1 << j);
tmp[1] &= ~(1 << (j+1));
}
j += 2;
}
memcpy(date,tmp,2);
}
//将16*16的数组转换后拷贝到font32中
void zoom16_to_font32(char *font16,char *font32)
{
char zoomout[32][4];
char zoom[2];
int j=0,i=0,t;
for(;j<32;j++)
{
int n = j%2;
zoom8(font16[j],zoom);
memcpy(zoomout[i]+n*2,zoom ,2);
if(n != 0)
{
memcpy(zoomout[i+1],zoomout[i],4);
i += 2;
}
}
memcpy(font32,zoomout,128);
}

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

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

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

 

void getCharLattice(char (*prt),char *buffer)
{
int fh;
long pos;
/* Position of file pointer */
long location;
long qh,wh;
if(prt[1] & 0xff)
{
fh = open( "/usr/lib/X11/fonts/HZK16", O_RDONLY );
// 汉字的区号
qh=prt[0]-0xa0;
// 汉字的位号
wh=prt[1]-0xa0;
// location=(94*(qh-1)+(wh-1))*一个点阵字模的字节数。
location=(94*(qh-1)+(wh-1))*32;
// 移动指针到location
pos = lseek( fh, location, SEEK_SET);
// 读数据
read( fh, buffer, 32);
char tmp[16][2];
memcpy(tmp,buffer,32);
transverse_modulus32(tmp,buffer);
}
else
{
((fh=open("/usr/lib/X11/fonts/ASC16",O_RDONLY))< 0) {
printf("Can not open ASC16rn");
}
location=prt[0]*16;
lseek(fh,location,SEEK_SET);
read(fh,buffer,16);
char tmp[32];
memcpy(tmp,buffer,16);
transverse_modulus16(tmp,buffer);
}
close( fh );
}

 

 

最后

以上就是温婉狗为你收集整理的点阵纵向取模以及放大算法的全部内容,希望文章能够帮你解决点阵纵向取模以及放大算法所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(36)

评论列表共有 0 条评论

立即
投稿
返回
顶部