编程实现根据指定文本生成电子印章(hnust)

编程实现根据指定文本生成电子印章(hnust)

题目描述
题目1:先为自己的名字制作一个汉字点阵txt文件,然后编程,通过程序读取汉字点阵txt文件中的信息,根据点阵信息决定向BMP文件中写入红点或白点数据,从而制作出自己的一枚电子印章。

编程前准备:利用隶书56点阵汉字字库文本文件LiShu56.txt(在老师提供的软件包中)制作印章字库文本文件XXX.txt(用记事本软件即可制作完成),要求与印章的摆放顺序一致。其中XXX指自定义的任意名称。如图2所示,是编者自己制作的字库文件文件xds.txt。

编程时的注意事项:

  1. 建立存储印章的文件XXX.bmp,然后按照BMP文件的格式往XXX.bmp文件中写入文件头、信息头。

  2. 然后根据XXX.txt文件中的内容确定颜色数据写入XXX.bmp文件中。XXX.txt文件中的一个字符对应于XXX.bmp文件中一个彩色点的数据(包括蓝、绿、红三个字节数据,若是红色点,一般置B=0、G=0,R=255)。构成字形的数据对应写入红色点数据,未构成字形的数据对应写入白色点数据。

  3. 检查文件头、信息头、彩色数据是否符合BMP文件的格式规范,若规范,则在windows环境下可以正常浏览和使用该电子印章图片了。

  4. 印章字库文本文件XXX.txt和生成的印章文件XXX.bmp通过命令行参数给定。假如程序编译连接后生成的可执行文件名为mySeal.exe,则用xds.txt制作印章xds.bmp的命令为:mySeal xds.txt xds.bmp。由图2生成的印章如图3所示。编程实现根据指定文本生成电子印章(hnust)_第1张图片
    编程实现根据指定文本生成电子印章(hnust)_第2张图片
    4.5 关键问题释疑
    4.5.1 彩色图像的显示原理

对于彩色图像,它的显示必须从三原色RGB概念说起。众所周知,自然界中的所有颜色都可以由红(R)、绿(G)、蓝(B)三原色组合而成。有的颜色含有红色成分多一些,其它成分少一些。针对含有红色成分的多少,可以人为地分成0到255共256个等级,0级表示不含红色成分,255级表示含有100%的红色成分。同样,绿色和蓝色也可以被分成256级。这样,根据红、绿、蓝各种不同的组合我们就能表示出256×256×256(约1600万)种颜色。表1是常见的一些颜色的RGB组合值。当一幅图中每个像素被赋予不同的RGB值时,就能呈现出五彩缤纷的颜色了,这就形成了彩色图像。

真彩色图像(又称24位色图像)的颜色种类高达256×256×256=224=16777216种,也就是包含上述提到的R、G、B颜色表示方法中所有的颜色。真彩色图像是说它具有显示所有颜色的能力,即最多可以包含所有的颜色。通常,在表示真彩色图时,每个像素直接用R、G、B这3个分量字节来表示,而不采用调色板技术。原因很简单:如果使用调色板,表示一个像素颜色在调色板中的索引要用24位(因为共有224种颜色,即调色板有224行),这和直接用R、G、B这3个分量表示用的字节数一样,不但没有节省任何空间,还要加上一个256×256×256×3=3×224字节的大调色板。所以真彩色图直接用R、G、B这3个分量表示。

表1 常见颜色的RGB组合
编程实现根据指定文本生成电子印章(hnust)_第3张图片
4.5.2 BMP彩色图像的文件格式

BMP图像文件格式,是微软公司为其WINDOWS环境设置的标准图像格式,并且内含了一套图像处理的API函数。随着WINDOWS在世界范围内的普及,BMP文件格式越来越多地被各种应用软件所支持。BMP图像文件是位图文件,位图表示的是将一幅图像分割成栅格,栅格的每一点称为像素,每一个像素具有自己的RGB值,即一幅位图是由一系列像素点构成的点阵。一个BMP文件包括位图文件头BITMAPFILEHEADER、位图信息头BITMAPINFOHEADER、调色板PALETTE和位图像素数据4个部分,如图5所示。其中,前面3部分的结构在windows.h中进行了定义。下面对它们进行详细说明。
编程实现根据指定文本生成电子印章(hnust)_第4张图片
一、位图文件头

位图文件头结构BITMAPFILEHEADER包含位图文件的类型大小信息和版面信息。结构如下:

typedef struct tagBITMAPFILEHEADER  // bmfh

{
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER;

这个结构的长度是固定的,为14个字节,各个域的说明如下:

bfType:指定文件类型,必须是0x4D42,即字符串"BM"。也就是说所有BMP文件的头两个字节都是"BM"。
bfSize:指定整个文件的大小(以字节为单位)。
bfReserved1:保留,一般为0。
bfReserved2:保留,一般为0。
bfOffBits:指定从文件头到实际的位图像素数据首部的字节偏移量。即图5中前3个部分的长度之和。

二、位图信息头

位图信息头结构BITMAPINFOHEADER包含图像本身的属性。其定义如下:

typedef struct tagBITMAPINFOHEADER  // bmih
{
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER;

这个结构的长度是固定的,为40个字节,各个域的说明如下:

biSize:指定 BITMAPINFOHEADER 结构的长度,为40个字节。
biWidth:指定位图的宽度(以象素为单位)。
biHeight:指定位图的高度(以象素为单位)。
biPlanes:指定目标设备的位面数。这个成员变量的值必须为1。
biBitCount:指定每个象素的位数。常用的值为1(黑白二色图)、4(16色图)、8(256色图)、24(真彩色图)。
biCompression:指定压缩位图的压缩类型。有效的值为BI_RGB(0), BI_RLE8(1), BI_RLE4(2), BI_BITFIELDS(3)。用得不多,在24位格式中,该变量被设置为0。
biSizeImage:指定图像的大小(以字节为单位)。如果位图的格式是BI_RGB,则将此成员变量设置为0是有效的。该值可以根据biWidth’和biHeight的乘积计算出来。要注意的是:上述公式中的biWidth’必须是4的整倍数(所以计算乘积时写的是biWidth’,表示大于或等于biWidth的、离4最近的整倍数。例如,若biWidth=240,则biWidth’=240;若biWidth=241,则biWidth’=244)。
biXPelsPerMeter:为位图指定目标设备的水平分辨率(以"象素/米"为单位)。
biYPelsPerMeter:为位图指定目标设备的垂直分辨率(以"象素/米"为单位)。
biClrUsed:指定位图实际用到的颜色数。如果该值为0,则用到的颜色数为2的biBitCount次方。
biClrImportant:指定对位图的显示有重要影响的颜色数。如果此值为0,则所有颜色都很重要。

三、调色板(注意:印章要求采用24位色,不需要调色板)

对于2色、16色和256色位图,需要调色板。调色板中的各个元素规定了第4部分(实际位图数据)对应的颜色值。对于24位色的真彩色图,不需要调色板,第2部分(信息头BITMAPINFOHEADER)后直接是位图数据。

调色板实际上是一个数组,共有biClrUsed个元素(如果此值为0,则有2的biBitCount次方个元素)。数组中每个元素的类型是一个RGBQUAD结构(4个字节),定义如下:

typedef struct tagRGBQUAD

{
BYTE rgbBlue; //该颜色的蓝色分量
BYTE rgbGreen; //该颜色的绿色分量
BYTE rgbRed; //该颜色的红色分量
BYTE rgbReserved; //保留值
} RGBQUAD;

四、图像数据

对于用到调色板的位图,图像数据就是该像素值在调色板中的索引值,对于24位色的真彩色图,图像数据就是实际的R、G、B值。下面对2色、16色、256色位图和真彩色位图分别加以介绍。

对于2色位图,用1位就可以表示该像素的颜色(一般0表示黑,1表示白),所以1个字节可以表示8个像素。
对于16色位图,用4位表示1个像素的颜色,所以1个字节可以表示2个像素。
对于256色位图,1个字节刚好可以表示1个像素。
对于24位色真彩色图(无调色板),3个字节才表示1个像素。
注意:

(1) BMP文件按从下到上,从左到右的顺序存储图像数据。即从文件中最先读到的是图像最下面一行的左边第一个像素,然后是左边第二个像素……接下来是倒数第二行左边第一个像素,左边第二个像素……依次类推,最后得到的是最上面一行的最右一个像素。

(2) 对于24位色真彩色位图而言,数据的排列顺序以图像的左下角为起点,从左到右、从下到上,每连续3个字节便描述图像一个像素点的颜色信息,这三个字节分别代表蓝、绿、红三基色在此像素中的亮度,若某连续三个字节为:00H,00H,FFH,则表示该像素的颜色为红色。24位真彩色位图中每个像素的RGB数据可以定义成如下结构:

typedef struct tagRGBDATA{
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
} RGBDATA;

五、BMP文件示例

24位色真彩色位图文件组成。用编辑软件(HEdit,老师的软件包中也会提供)查看24位色真彩色位图文件Lena.bmp的组成,有如下3部分:

1.24位色真彩色位图的文件头。如图6深色部分所示,从文件存放首地址0x0000开始,共14个字节。
编程实现根据指定文本生成电子印章(hnust)_第5张图片
2.24位色真彩色位图的信息头。如图7深色部分所示,从文件存放地址0x000E开始,共40个字节。
编程实现根据指定文本生成电子印章(hnust)_第6张图片
3.24位色真彩色位图的实际像素数据。如图8深色部分所示,从文件存放地址0x0036开始,共512×512×3=786432个字节。
编程实现根据指定文本生成电子印章(hnust)_第7张图片
通过以上实例,我们熟悉了BMP彩色图像的格式,然后我们按格式创建BMP文件,并将印章点阵数据写入,则可制作出自己的印章BMP图像。

4.5.3 如何制作BMP文件

制作一个可在windows中正常浏览和使用的BMP文件,主要包括如下四个步骤:

第一步:用命令行中给出的文件名新建一BMP文件,此时还是一个空文件;

第二步:置文件头数据并写入BMP文件;

第三步:置信息头数据并写入BMP文件;

第四步:置图像RGB数据并写入BMP文件。

/****************************************************************************

**** FileName: demo.c

**** Function: 真彩色bmp图片文件的创建

**** Usage: demo xxxx.bmp

*****************************************************************************/

#include

#include

#include

#include

#include

#include

typedef unsigned char BYTE;

typedef unsigned short WORD;

typedef unsigned long DWORD;

/**** The file header of bmp file 文件头*****/

#include //This file turns 2 byte packing of structures on, then sizeof(BITMAPFILEHEADER)=14, otherwise sizeof(BITMAPFILEHEADER)=16

typedef struct tagBITMAPFILEHEADER {
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfoffBits;
} BITMAPFILEHEADER;

#include //This file turns packing of structures off
/**** The information header of bmp file 信息头*****/
typedef struct tagBITMAPINFOHEADER {
DWORD biSize;
DWORD biWidth;
DWORD biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompress;
DWORD biSizeImage;
DWORD biXPeIsPerMeter;
DWORD biYPeIsPerMeter;
DWORD biCIrUsed;
DWORD biClrImprotant;
} BITMAPINFOHEADER;

/**** The RGB data of bmp file 图像RGB数据*****/
typedef struct tagRGBDATA{
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
} RGBDATA;

int main(int argc, char *argv[])
{
RGBDATA *bmpData=NULL; //图像数据指针
FILE fp; //BMP文件指针
long i,j,k;
long width=300; //图像宽度
long height=300; //图像高度
long dataSize=width
height;
BITMAPFILEHEADER bmfHeader;
BITMAPINFOHEADER bmiHeader;
if(argc<2)
{
printf("\n 请指定您要生成的BMP文件名!\n");
printf("\n 方法1:在cmd窗口输入: demo xxxx.bmp 后回车执行!\n");
printf("\n 方法2:在VC的工程设置中添加参数: xxxx.bmp 后编译运行!\n");
printf("\n 功能: 根据设定红绿蓝三色分量的值,控制显示不同的彩色条纹!\n\n");
exit(0);
}
printf("\n ******************************************************************\n");
printf("\n 感谢您使用BMP图片文件制作DEMO程序 \n");
printf("\n 作者:向德生 \n");
printf("\n 日期:2010年5月12日 \n");
printf("\n 目的:编制印章生成程序时,供参考! \n");
printf("\n 功能:根据设定红绿蓝三色分量的值,控制显示不同的彩色条纹!\n\n");
printf("\n ****************************************************************\n\n");
//第一步:用命令行中给出的文件名新建一BMP文件,此时还是一个空文件
if((fp=fopen(argv[1], “wb+”))==NULL)
{
printf(“Cannot open BMP file!”);
exit(0);
}
//第二步:置文件头数据并写入BMP文件
bmfHeader.bfType=0x4d42;
bmfHeader.bfSize=14+40+width
height
3;
bmfHeader.bfReserved1=0;
bmfHeader.bfReserved2=0;
bmfHeader.bfoffBits=0x36;
fwrite(&bmfHeader, sizeof(BITMAPFILEHEADER), 1, fp);

//第三步:置信息头数据并写入BMP文件
bmiHeader.biSize=40;
bmiHeader.biWidth=width;
bmiHeader.biHeight=height;
bmiHeader.biPlanes=1;
bmiHeader.biBitCount=24;
bmiHeader.biCompress=0;
bmiHeader.biSizeImage=widthheight3;
bmiHeader.biXPeIsPerMeter=0;
bmiHeader.biYPeIsPerMeter=0;
bmiHeader.biCIrUsed=0;
bmiHeader.biClrImprotant=0;
fwrite(&bmiHeader, sizeof(BITMAPINFOHEADER), 1, fp);

//第四步:置图像数据并写入BMP文件
//分配足够内存,让bmpData指向这块内存,用于存放图像各象素点的RGB分量值
if((bmpData=(RGBDATA*)malloc(widthheight3))==NULL)
{
printf(“bmpData memory malloc error!”);
}

//先在bmpData所指内存中置图像RGB数据,然后将所有数据写入BMP文件
for(i=0;i {
for(j=0;j {
k=(height-i-1)*width + j;//计算第i行第j列图像数据在bmpData[]数组中的位置
if(i<100)//上100行只置红色分量值,显示为红色
{
bmpData[k].rgbBlue=0;
bmpData[k].rgbGreen=0;
bmpData[k].rgbRed=255;//红色分量值为:255
}
else
if(i<200)//中100行只置绿色分量值,显示为绿色
{
bmpData[k].rgbBlue=0;
bmpData[k].rgbGreen=255;//绿色分量值为:255
bmpData[k].rgbRed=0;
}
else
if(i<300)//下100行只置蓝色分量值,显示为蓝色
{
bmpData[k].rgbBlue=255;//蓝色分量值为:255
bmpData[k].rgbGreen=0;
bmpData[k].rgbRed=0;
}
}
}
fwrite(bmpData,sizeof(RGBDATA),dataSize,fp);//将bmpData所指的RGB数据一次性写入BMP文件
printf("\n 恭喜您!BMP文件已经成功生成!\n");
printf("\n 请在当前目录下查看生成的BMP文件%s\n\n",argv[1]);
free(bmpData); //释放bmpData所指的内存空间
bmpData=NULL; //置bmpData为空指针
fclose(fp); //关闭fp所指文件
}

该程序生成的大小为300×300的BMP图片,可在运行本程序的目录下查看。
重要提示:任务2的编程与本示例编程的不同主要是在第四步。

4.5.4 如何根据输入的汉字确定其编码

我们看到屏幕上显示的汉字的字型有两种表达方式:一种称为矢量方式,一种称为点阵方式。其中的点阵方式较为简单,其原理就是好比:铺地砖。有的铺为白色,有的铺为黑色,只要精心安排,就会组成我们希望的图案,当然也可以是汉字。

瓷砖越多,铺出的图案效果越细腻,这就是点阵的规模。56点阵汉字用56 x 56 = 3136个像素点来描绘。

当我们需要记录一个汉字信息的时候,当然不是存储汉字的字型,而是存储它的编码。汉字可以有多种编码的规则,其中GB2312的编码规则是:一个汉字用两个字节表示,前一个字节表示区号,后一个表示区中的偏移序号。

每个区有94个汉字。区号和序号的编码都是从 0xA1开始(为了避免和西文冲突)。已知某个汉字的GB2312编码,就可以计算出它在二进制字模文件中所在的绝对位置。我们在本次课程设计中,不用二进制字模文件。而是用文本文件LiShu56.txt,因为其中的点阵信息非常形象直观,适合我们这些C的初学者。

下面程序能从键盘获得一个或多个汉字的编码,如输入“向”,则其编码为CF F2,有了这个编码,我们就可以在LiShu56.txt文件中查找其点阵信息。

#include
int main(void)
{
int i, len;
unsigned char BM[100];
printf(“请输入一个或多个汉字:”);
scanf("%s",BM);
for(len=0;BM[len]!=’\0’;len++);
for(i=0;i printf(“BM[%d]=%x\n”,i,BM[i]); //输入"向",则其编码为CF F2
return 0;
}

4.5.5 如何将编码变成字符串?

我们知道,“向”的编码为2个字节,分别是CF和 F2,如何将其变成字符串(包括字符’C’、’F’、’F’、’2’,占4个字节)存入字符数组中,以便于在LiShu56.txt文件中查找其点阵信息。
#include
int main(void)
{
int i, len;
unsigned char BM[100];
char str[200];
printf(“请输入一个或多个汉字:”);
scanf("%s",BM);
for(len=0;BM[len]!=’\0’;len++);
for(i=0;i printf(“BM[%d]=%x\n”,i,BM[i]); //输入"向",则其编码为CF  F2
printf(“将编码转换成字符并显示:”);
for(i=0;i sprintf(str+2i,"%x",BM[i]); //编码->字符,并存入str数组
for(i=0;i<2
len;i++)
printf("%c ",str[i]);
return 0;
}

例如,我想制作自己的印章,先输入4个印章上显示的汉字“向德生印”,通过上面的程序就可以得到相应的编码(十六进制表示)。其中,“向”字的编码为cff2,“德”字的编码为b5c2,“生”字的编码为c9fa,“印”字的编码为“d3a1”。然后将这4个汉字的十六进制编码转换成对应的字符“c f f 2”、“b 5 c 2”、“c 9 f a”、“d 3 a 1”。执行效果如下图所示。
编程实现根据指定文本生成电子印章(hnust)_第8张图片当我们输入要生成印章的汉字后,首先将编码转换成“字符”,然后就可以利用这些字符在LiShu56.txt文件中查找匹配其点阵信息。原理就是:利用这些字符,在文本文件LiShu56.txt中搜索,有匹配的编码,就将其后的点阵信息读出并写入图像文件,则可生成印章图片。

注意:4个汉字处在图片的不同位置,在将各个汉字的点阵信息写入图像文件中时,要通过适当的算法对各汉字的位置进行调整。

解题过程如下:

1.在desktop(桌面)上开了一个名为bmp的文件夹,
2. 然后把代码所生成的exe文件与含有名字的txt文件放进了这个文件夹(文件在软件包内找)
3. 利用cmd指令(win+R)先输入cd desktop(桌面)回车
再输入cd bmp(找你桌面叫bmp的文件)回车
再输入demo xxx. bmp(给bmp图片命名)
编程实现根据指定文本生成电子印章(hnust)_第9张图片
输入所给的图片名(01.bmp)查看代码所生成的图片
编程实现根据指定文本生成电子印章(hnust)_第10张图片
理解之后接下来修改第四步代码,找到你所制作的txt文件,放入建立的桌面bmp文件中,(可直接放老师的文件xds2.txt),那四个字是由“X”和“_”组成的,只要把是X的上红色,上白色就可以达到题意,然后还有一个问题怎么让你的程序知道哪里是x哪里是 :读入文件,定义一个二维数组,将文件内容写入二维数组。

解题代码如下:

/*********************************************************************************
 ****  FileName:  demo.c
 ****  Function:  真彩色bmp图片文件的创建          
 ****  Usage:     demo  xxxx.bmp 
 ****  Author:    xiangdesheng  
 ****  Date:      2010-05-12        
 *********************************************************************************/
#include     
#include     
#include     
#include    
#include  
#include 

typedef unsigned char BYTE;   
typedef unsigned short WORD;   
typedef unsigned long DWORD;   
   
/****  The file header of bmp file 位图文件头*****/
#include  //This file turns 2 byte packing of structures on, then sizeof(BITMAPFILEHEADER)=14, otherwise sizeof(BITMAPFILEHEADER)=16
typedef struct tagBITMAPFILEHEADER {   
    WORD bfType;   
    DWORD bfSize;   
    WORD bfReserved1;   
    WORD bfReserved2;
    DWORD bfoffBits;                                                
} BITMAPFILEHEADER; 
#include  //This file turns packing of structures off 
   
/****  The information header of bmp file 位图信息头*****/
typedef struct tagBITMAPINFOHEADER {   
    DWORD biSize;   
    DWORD biWidth;   
    DWORD biHeight;   
    WORD  biPlanes;   
    WORD  biBitCount;      
    DWORD biCompress;
    DWORD biSizeImage;   
    DWORD biXPeIsPerMeter;   
    DWORD biYPeIsPerMeter;   
    DWORD biCIrUsed;   
    DWORD biClrImprotant;   
} BITMAPINFOHEADER;   
   
/****  The RGB data of bmp file 图像RGB数据*****/
typedef struct tagRGBDATA{   
    BYTE rgbBlue;       
    BYTE rgbGreen; 
	BYTE rgbRed;   
} RGBDATA; 

int main(int argc, char *argv[])
{
	RGBDATA *bmpData=NULL;	//图像数据指针
	FILE *fp, *fq;				//BMP文件指针
	long i,j,k;
	//================================================================================================
	long width=112;			//图像宽度
	long height=113;		//图像高度
	long dataSize=width*height;
	BITMAPFILEHEADER bmfHeader;   
	BITMAPINFOHEADER bmiHeader; 

	if(argc<2)
	{
		printf("\n    请指定您要生成的BMP文件名!\n");
		printf("\n    方法1:在cmd窗口输入: demo  xxxx.bmp 后回车执行!\n");
		printf("\n    方法2:在VC的工程设置中添加参数: xxxx.bmp 后编译运行!\n");
		printf("\n    功能: 根据设定红绿蓝三色分量的值,控制显示不同的彩色条纹!\n\n");
		exit(0);
	}		

	printf("\n    ********************************************************************************\n");
	printf("\n         感谢您使用BMP图片文件制作DEMO程序                 \n");
	printf("\n             作者:向德生                 \n");
	printf("\n             日期:2010年5月12日                 \n");
	printf("\n             目的:编制印章生成程序时,供参考!       \n");
	printf("\n             功能:根据设定红绿蓝三色分量的值,控制显示不同的彩色条纹!\n\n");
	printf("\n    ********************************************************************************\n\n");

    //第一步:用命令行中给出的文件名新建一BMP文件,此时还是一个空文件
	if((fp=fopen(argv[1], "wb+"))==NULL)
	{
		printf("Cannot open BMP file!");
		exit(0);
	}
	if((fq=fopen("xds2.txt", "r"))==NULL)
	{
		printf("Cannot open BMP file!");
		exit(0);
	}

	//第二步:置文件头数据并写入BMP文件
	bmfHeader.bfType=0x4d42;
	bmfHeader.bfSize=14+40+width*height*3;
	bmfHeader.bfReserved1=0;
	bmfHeader.bfReserved2=0;
	bmfHeader.bfoffBits=0x36;
    fwrite(&bmfHeader, sizeof(BITMAPFILEHEADER), 1, fp);

	//第三步:置信息头数据并写入BMP文件
	bmiHeader.biSize=40;
	bmiHeader.biWidth=width;
	bmiHeader.biHeight=height;
	bmiHeader.biPlanes=1;
	bmiHeader.biBitCount=24;
	bmiHeader.biCompress=0;
	bmiHeader.biSizeImage=width*height*3;
	bmiHeader.biXPeIsPerMeter=0;
	bmiHeader.biYPeIsPerMeter=0;
	bmiHeader.biCIrUsed=0;
	bmiHeader.biClrImprotant=0;
    fwrite(&bmiHeader, sizeof(BITMAPINFOHEADER), 1, fp);
	//第四步:置图像RGB数据并写入BMP文件
	//分配足够内存,让bmpData指向这块内存,用于存放图像各象素点的RGB分量值
	if((bmpData=(RGBDATA*)malloc(width*height*3))==NULL)
	{
		printf("bmpData memory malloc error!");
	}

	char a[112][113];//根据xds2.txt文件的行列数确定
	for(i=0;i<112;i++)
	   for(j=0;j<113;j++){
	   	  fscanf(fq,"%c",&a[i][j]);
	   }//将xds2.txt的内容写入数组
	fclose(fq);//记得关闭文件
	//先在bmpData所指内存中置图像RGB数据,然后将所有数据写入BMP文件
	for(i=0;i<112;i++)
	{
		for(j=0;j<113;j++)
		{
			k=(height-i-1)*width + j;
			if(a[i][j]=='X'||i<=2||j<=2||i>=height-3||j>=width-3)
			{
				bmpData[k].rgbBlue=0;
				bmpData[k].rgbGreen=0;
				bmpData[k].rgbRed=255;//红色分量值为:255
			}
			else if(a[i][j]=='_')
				{
					bmpData[k].rgbBlue=255;
					bmpData[k].rgbGreen=255; 
					bmpData[k].rgbRed=255;//白色
				}
		}
	}
	fwrite(bmpData,sizeof(RGBDATA),dataSize,fp);//将bmpData所指内存中的RGB数据一次性写入BMP文件

	printf("\n    恭喜您!BMP文件已经成功生成!\n");
	printf("\n    请在当前目录下查看生成的BMP文件%s\n\n",argv[1]);

	free(bmpData);	//释放bmpData所指的内存空间
	bmpData=NULL;	//置bmpData为空指针
	fclose(fp);		//关闭fp所指文件
}

在cmd中运行得到图片如下:
编程实现根据指定文本生成电子印章(hnust)_第11张图片
完成任务,科大学子加油噢!!!

以下是在同学那里要到的编码,可以生成自己的名字,完成任务三的题目二

#include 
#include 
#include 
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
/****  The file header of bmp file 文件头*****/
#pragma pack(push)
#pragma pack(2) //避免结构体内存对齐,按2b对齐
typedef struct tagBITMAPFILEHEADER
{
    WORD bfType;
    DWORD bfSize;
    WORD bfReserved1;
    WORD bfReserved2;
    DWORD bfOffBits;
} BITMAPFILEHEADER;
/****  The information header of bmp file 信息头*****/
#pragma pack(pop)//使上一个失效
typedef struct tagBITMAPINFOHEADER
{
    DWORD biSize;
    DWORD biWidth;
    DWORD biHeight;
    WORD biPlanes;
    WORD biBitCount;
    DWORD biCompress;
    DWORD biSizeImage;
    DWORD biXPeIsPerMeter;
    DWORD biYPeIsPerMeter;
    DWORD biCIrUsed;
    DWORD biClrImprotant;
} BITMAPINFOHEADER;

/****  The RGB data of bmp file 图像 RGB 数据*****/
typedef struct tagRGBDATA
{
    BYTE rgbBlue;
    BYTE rgbGreen;
    BYTE rgbRed;
} RGBDATA;
long position(int x,int y)
{
    x = x-0xb0, y = y-0xa1;
    int k = 715+x * 94 + y;
    if(k>=4475)
        k -= 5;
    return 68 + 17 + 4 + 15 + 11 + k * (15 + 11 + 4 + 56 * 65);
}
void indata(FILE *fpp,char data[160][160] )  //从字库中导入数据
{
    char input[100];   //要打印的汉字
    int judge = 0,len;
    while(!judge)
    {
        judge = 1;
        printf("\n    请输入印章上的4个汉字:  ");
        gets(input);
        len = strlen(input);
        for (int i = 0; input[i]; i++)
          if(input[i]>=0&&input[i]<=127)  //判断是否有非汉字字符
            {
                judge = 0;
                printf("\n您输入了非汉字字符,请重新输入:\n");
                break;
            }
    }
    for (int i = 0; i < len;i=i+2)
    {
        long  k = position(input[i]&0xff, input[i + 1]&0xff); //找到该汉字在文件中的位置
        fseek(fpp, k, SEEK_SET); //将文件指针跳转到汉字所在位置
        int row, end, column;
        if(i==0)row = 0, end = 56, column = 56; //右上角
        if(i==2)row = 56, end = 113, column = 56;//右下角
        if(i==4)row = 0, end = 56, column = 0;//左上角
        if(i==6)row = 56, end = 113, column = 0;//左下角
        for (; row < end;row++)
              {
                    char ch=fgetc(fpp);
                    int _column = column;
                    while (ch != '\n')
                    {  if(ch!=',')data[row][_column++] = ch; //去除汉字点库中的逗号
                       ch = fgetc(fpp);
                    }
              }        
    }
}
int main(int argc, char *argv[])
{
    RGBDATA *bmpData = NULL; //图像数据指针
    FILE *fp, *fpp;          //fp为BMP文件指针,fpp为汉字点阵指针;
    long i, j, k;
    long width = 112+16;  //图像宽度
    long height =113+16; //图像高度
    long dataSize = width * height;
    BITMAPFILEHEADER bmfHeader;
    BITMAPINFOHEADER bmiHeader;
    if (argc < 3)
    {
        printf("    ********************************************************************\n");
        printf("\n              欢迎您使用电子印章制作软件\n");
        printf("\n    命令格式:mySeal ls.txt xxxx.bmp\n");
        printf("\n    主要功能: 实现根据点阵信息文件\"ls.txt\"制作对应的电子印章文件\"xxxx.bmp\"\n");
        printf("\n    使用说明: \n");
        printf("\n              1:请按上面的格式输入命令,其中xxxx.bmp为您自定义的名称, 扩展名为.bmp\n");
        printf("\n              2:执行本命令后会提示您输入4个汉字,用于生成方形印章bmp文件,然后程序\n");
        printf("\n                会根据您提供的汉字自动从隶书56点阵字形文本文件LiShu56.txt中提取相\n");
        printf("\n                应的点阵信息,并生成印章bmp文件!\n");
        printf("\n              3:如果想生成行楷字体的印章,请将上面命令中的ls.txt换成xk.txt即可!\n");

    }
    //第一步:用命令行中给出的文件名新建一 BMP 文件,此时还是一个空文件
    if ((fpp = fopen(argv[1], "r")) == NULL)
    {
        printf("Cannot open txt file!");
        exit(0);
    }
    if ((fp = fopen(argv[2], "wb+")) == NULL)
    {
        printf("Cannot open bmp file!");
        exit(0);
    }
    //第二步:置文件头数据并写入 BMP 文件
    bmfHeader.bfType = 0x4d42;
    bmfHeader.bfSize = 14 + 40 + width * height * 3;
    bmfHeader.bfReserved1 = 0;
    bmfHeader.bfReserved2 = 0;
    bmfHeader.bfOffBits = 0x36;
    fwrite(&bmfHeader, sizeof(BITMAPFILEHEADER), 1, fp);
    //第三步:置信息头数据并写入 BMP 文件
    bmiHeader.biSize = 40;
    bmiHeader.biWidth = width;
    bmiHeader.biHeight = height;
    bmiHeader.biPlanes = 1;
    bmiHeader.biBitCount = 24;
    bmiHeader.biCompress = 0;
    bmiHeader.biSizeImage = width * height * 3;
    bmiHeader.biXPeIsPerMeter = 0;
    bmiHeader.biYPeIsPerMeter = 0;
    bmiHeader.biCIrUsed = 0;
    bmiHeader.biClrImprotant = 0;
    fwrite(&bmiHeader, sizeof(BITMAPINFOHEADER), 1, fp);

    //第四步:置图像数据并写入 BMP 文件
    //分配足够内存,让 bmpData 指向这块内存,用于存放图像各象素点的 RGB 分量值
    if ((bmpData = (RGBDATA *)malloc(width * height * 3)) == NULL)
    {
        printf("bmpData memory malloc error!\n");
        exit(0);
    }
    //先在 bmpData 所指内存中置图像 RGB 数据,然后将所有数据写入 BMP 文件
    char data [160][160];
    indata(fpp, data);   //根据输入从汉字点阵中寻找数据
    for (i = 0; i < height; i++)
    {
        for (j = 0; j < width; j++)
        {
            k = (height - i - 1) * width + j; //计算第 i 行第 j 列图像数据在 bmpData[]数组中的位置
            if(i<8||j<8||i>=height-8||j>=width-8)  //加边框,并设置为红色边框。
             {  bmpData[k].rgbBlue = 0;
                bmpData[k].rgbGreen = 0;
                bmpData[k].rgbRed = 255;
                continue;
             }
            if (data[i-8][j-8] == 'X')   //构成字体的字符为红色
            {   bmpData[k].rgbBlue = 0;
                bmpData[k].rgbGreen = 0;
                bmpData[k].rgbRed = 255;
            }
            else                        //不构成字体的字符为白色
            {
                bmpData[k].rgbBlue = 255;
                bmpData[k].rgbGreen = 255;
                bmpData[k].rgbRed = 255;
            }
        }
    }
    fwrite(bmpData, sizeof(RGBDATA), dataSize, fp); //将 bmpData 所指的 RGB 数据一次性写入 BMP 文件
    printf("\n    恭喜您!BMP 文件已经成功生成!\n");
    printf("\n    请在当前目录下查看生成的 BMP 文件%s\n\n", argv[2]);
    free(bmpData);  //释放 bmpData 所指的内存空间
    bmpData = NULL; //置 bmpData 为空指针
    fclose(fp);     //关闭 fp 所指文件
    fclose(fpp);    //关闭fpp所指文件
}

看图
编程实现根据指定文本生成电子印章(hnust)_第12张图片
编程实现根据指定文本生成电子印章(hnust)_第13张图片
感谢这位同学无私提供代码供我们学习,加油!!!!

你可能感兴趣的:(趣味程序设计,c语言)