1.原理
以汉字的机内码或区位码作为输入值,根据汉字字模在相应汉字库中的存贮格式,提取汉字的字形数据。放大汉字的方法一般是将字形数据中的每一位用一个长方形或椭圆来显示,其中,长方形的宽、高和椭圆的长轴、短轴分别为汉字横向放大倍数和纵向放大倍数。这里介绍汉字放大的方法是:横向放大m倍,则在原亮点的位置开始,在屏幕上横向写m个点;纵向放大m被,则在原亮点的位置开始,纵向写m个点。其中,写点函数采用int 10H的12号子功能,入口参数如下:
调用:AH=0CH
AL=像素值
CX=列数(X坐标)
DX=行数(Y坐标)
返回:无
若置AL的第七位,新的像素值将于当前像素值的内容亦或。写点函数的源代码如下:
void putpoint(int x,int y,int color,int how)
{
union REGS r;
if(how==0x18)
{
color = color|128;
}
r.h.bh = 0;
r.h.ah = 12;
r.h.al = color;
r.h.dx = y;
r.h.cx = x;
int86(0x10,&r,&r);
}
2.汉字机内码的计算
利用中文字处理软件(如CCED、汉化WS、PE等)编辑所需输入的汉字,再利用DEBUG或PCTOOLS工具软件读出其机内码即可。但若有区位码表,也可查出相应汉字的区位码,通过下属公式算出汉字机内码(区位码的区码、位码用16进制表示)。
汉字机内码 = 汉字ACSII码 + 8080H = (区位码+2020H)+8080H = 区位码+ A0A0H
3.汉字字模序号的计算
由于不同的中文操作系统所使用的点阵字库不同,所以字模地址的计算公式也可能不同。但一般汉字库均符合国标GB 2312-80的规定,每一个16X16点阵汉字需占32字节,24X24点阵需72字节。下面以最常见的几个汉字库为例说明。
a.长城机上汉字库clib24共存放8434个24X24点阵字模,每个字模均统一占用72个字节,前256个字模对应ASCII码,后8178个字模对应87X94区的GB2312-80字符集。国标一、二级汉字和其它图形字符的记录号可由下式确定。假设N1、N2为其机内码第一、二字节,则有:
RECORD_NUM = (N1-A1H)*5EH+N2-A1H+100H
b.CCDOS 2.13H的HZK24的字模序号计算公式为:
RECORD_NUM = (N1-B0H)*5EH+(N2-A1H)
c.UCDOS中的cclib.dat是16X16 点阵字库,其字模序号计算公式为:
RECORD_NUM = (N1-A1H)*0X5E+N2-A1H
d.CCDOS2.13H的HZK16的字模序号计算公式为:
RECORD_NUM =(N1-B0H)*5EH+N2-A1H+15*94
本文程序就是读HZK16而得到字模点阵信息的。
4.汉字字模存储格式
16*16点阵字库每个字模共占用 16/8*16=32个字节, 24X24点阵字库每个字模共占用24/8*24=72个字节。字模的存贮格式如下:
D0.D7 D0.D7
0字节 1字节
2字节 3字节
… …
28字节 29字节
30字节 31字节
16X16点阵字模存储格式
D7.D0 0字节 3字节…66字节 69字节
D7.D0 1字节 4字节…67字节 70字节
D7.D0 2字节 5字节…68字节 71字节
5.源代码
#include <stdio.h>
#include <alloc.h>
#include <dos.h>
#include <conio.h>
#define HENG_FD 3//横向放大倍数
#define ZONG_FD 3//纵向放大倍数
#define HZ_JIANGE 4//汉字的间隔
#define XPOSITION 60//汉字起始位置
#define YPOSITION 100//汉字起始位置
void putpoint(int,int,int,int);
void set_mode(int mode);
void main(void)
{
FILE* fp;
char dot[33],*hz_matrix;
unsigned int ch;
long int order;
register int i,j,k,t,p = 0;
int x,y;
int hzcode[7]= {0xbaba,0xd6d7,0xc5b7,0xf3b4,0xccb3,0xf2d0,0};
set_mode(16);
if((fp=fopen(“hzk16″,”rb”))==NULL)
{
set_mode(3);
printf(“Do not open HZK16S
“);
exit(1);
}
if((hz_matrix=(char*)malloc(256))==NULL)
{
set_mode(3);
printf(“Not enough memory
“);
exit(1);
}
x = XPOSITION;
y = YPOSITION;
while(hzcode[p])
{
k = 0;
fseek(fp,0l,SEEK_SET);
//计算偏移量
order = (long)(((hzcode[p]>>8)&007f)-0x21+94*((hzcode[p]&0x007f)-0x30)+15*94)*32;
fseek(fp,(long)order,SEEK_SET);
//读取汉字点阵信息
if(!fread(dot,32,1,fp))
{
set_mode(3);
printf(”
Read hz dot matrix error
“);
exit(1);
}
if(x+HENG_FD*16>639)
{
set_mode(3);
printf(“Having reached the right margin of the screen
“);
exit(1);
}
//把汉字点阵信息放入HZ_MATRIX[]中
for(i=0;i<16;i++,k+=2)
{
ch = ((unsigned char)dot[k]<<8)+(unsigned char)dot[k+1];
for(j=0;j<16;j++,ch<<=1)
{
if(ch&0x8000)
{
hz_matrix[j+16*i] = 1;
}
else
{
hz_matrix[j+16*i] = 0;
}
}
}
for(t=0;t<16;t++)//处理列(纵向)
{
for(j=0;j<16;j++)//处理行(横向)
{
if(hz_matrix[j+16*t])//该点是亮点
{
for(i=0;i<HENG_FD;i++)//横向放大该亮点
{
putpoint(x+i+HENG_FD*j,y+t*ZONG_FD,4,0×18);
for(k=1;k<ZONG_FD;k++)//纵向放大该亮点
{
putpoint(x+i+HENG_FD*j,y+k+t*ZONG_FD,4,0×18);
}
}
}
}
}
p++;
//下一个汉字的起始坐标
x = XPOSITION +HENG_FD*(16+HZ_JIANGE)*p;
}
free(hz_matrix);
getch();
set_mode(3);
}
void putpoint(int x,int y,int color,int how)
{
union REGS r;
if(how==0x18)
{
color|=128;
}
r.h.bh = 0;
r.h.ah = 12;
r.h.al = color;
r.x.dx = y;
r.x.cx = x;
int86(0x10,&r,&r);
}
void set_mode(int mode)
{
union REGS r;
r.h.al = mode;
r.h.ah = 0;
int86(0x10,&r,&r);
}