for(k=0;k<8;k++)
if(mat[j*n+i]&(0x80>>k))/*测试为1的位如此显示*/
putpixel(x+i*8+k,y+j,color);
}
⏹
该模块的功能实现主要是用到了图形区域的重绘显示,并返回屏幕的纵坐标值,以实现功能的选择。
主要代码实现如下:
intworkinterface()
{charkey;
intx=220,y1=140,y2;
initgr
(1);/*打开图形模式*/
setfillstyle(1,BLUE);/*设置填充模式和颜色*/
bar(x,y1,x+200,y1+50);/*画长方体并填正面*/
setcolor(BLUE);
setfillstyle(2,BLUE);
draw();/*输出菜单*/
prompt(y1);
while((key=getch())!
='\r')
{if(key==72)/*上移*/
{if(y1==140)
{cleardevice();/*清楚图形屏幕*/
y2=y1+100;
setfillstyle(1,BLUE);
bar(x,y2,x+200,y2+50);/*画长方体*/
setcolor(BLUE);
setfillstyle(2,BLUE);
draw();//绘制图形
y1=y2;
prompt(y1);/*操作提示*/
}
else
{cleardevice();
y2=y2-50;
setfillstyle(1,BLUE);/*设置填充模式和颜色*/
bar(x,y2,x+200,y2+50);/*画长方体并填正面*/
setcolor(BLUE);
setfillstyle(2,BLUE);
draw();
y1=y2;
prompt(y1);
}
}
elseif(key==80)/*下移*/
{if(y1==240)
{cleardevice();
y2=y1-100;
setfillstyle(1,BLUE);/*设置填充模式和颜色*/
bar(x,y2,x+200,y2+50);/*画长方体并填正面*/
setcolor(BLUE);
setfillstyle(2,BLUE);
draw();
y1=y2;
prompt(y1);/*操作提示*/
}
else
{cleardevice();
prompt
(1);
y2=y1+50;
setfillstyle(1,BLUE);/*设置填充模式和颜色*/
bar(x,y2,x+200,y2+50);/*画长方体并填正面*/
setcolor(BLUE);
setfillstyle(2,BLUE);
draw();
y1=y2;
prompt(y1);
}
}
}
initgr(0);/*关闭图形模式*/
returny1;
}
⏹4.4图片浏览模块〔自动浏览模式、手动浏览模式〕
●4.4.1链表的创建
链表是一种比拟重要的数据结构,它采用了动态分配内存的方法为一个结构分配内存空间。
每一次分配一块内存空间用来存放一个数据,我们称之为一个节点。
链表主要有“单链表〞,“单循环链表〞,“双链表〞,“双循环链表〞四种类型。
在C语言中,链表通常都是通过结构体和指针来实现的。
单链表:
每个节点只有一个指针域,指针域存储下一个节点的地址。
尾节点的指针域为空。
单循环链表:
在单链表的根底上,在尾节点的指针域中存放头结点的地址,形成一个环。
双链表:
每个结点有两个指针域:
前驱结点指针域,后继结点指针域,分别存放前一个和后一个结点的地址,头结点的前驱结点指针域为空,尾结点的后继结点指针域为空。
双循环链表:
在双链表的根底上,在尾结点的后继结点指针域中存放头结点的地址,在头结点的前驱指针域中存放尾结点的地址,形成一个双环。
本系统用到了双链表,在存放图片的文件夹〔image〕目录下搜索bmp格式的文件,将文件名存储到一个双链表中。
实现代码如下所示:
structbmpfile
{charfilename[20];
structbmpfile*prec;/*前驱节点*/
structbmpfile*next;/*后继节点*/
};
structbmpfile*file_link()
{structffblkfile;
structbmpfile*head=NULL,*cur=NULL,*newp=NULL;
registerintdone;
char*path="image\\";
char*fname;
done=findfirst("image\\*.bmp",&file,0);/*在image目录下搜索第一个.bmp文件*/
while(!
done)
{newp=(structbmpfile*)malloc(sizeof(structbmpfile));/*创建新节点*/
if(head==NULL)/*创建头节点*/
{head=newp;head->prec=NULL;}
else
{cur=head;
while(cur->next!
=NULL){cur=cur->next;}
cur->next=newp;
cur->next->prec=cur;
}
cur=newp;
strcpy(fname,path);
strcat(fname,file.ff_name);
strcpy(cur->filename,fname);
cur->next=NULL;
done=findnext(&file);/*继续搜索下一个与file类型相匹配的文件*/
}
returnhead;
}
●4.4.2BMP图片显示
这是本系统中的难点,也是关键技术。
Bmp图片就是通常所说的位图,,是一种与硬件设备无关的图像文件格式,使用非常广。
它采用位映射存储格式,除了图像深度可选以外,不采用其他任何压缩,因此,BMP文件所占用的空间很大。
BMP文件的图像深度可选lbit、4bit、8bit与24bit。
BMP文件存储数据时,图像的扫描方式是按从左到右、从下到上的顺序。
由于BMP文件格式是Windows环境中交换与图有关的数据的一种标准,因此在Windows环境中运行的图形图像软件都支持BMP图像格式。
●4.4.3BMP图片格式文件结构分析
典型的BMP图像文件由四局部组成:
1:
位图文件头数据结构(14个字节):
它包含BMP图像文件的类型、显示内容等信息;其结构定义如下:
typedefstructtagBITMAPFILEHEADER{//文件头的偏移量表示,以字节为单位
WORDbfType;//位图文件的类型,必须为BMP(0-1字节)
DWORDbfSize;//位图文件的大小,以字节为单位(2-5字节)
WORDbfReserved1;//位图文件保存字,必须为0(6-7字节)
WORDbfReserved2;//位图文件保存字,必须为0(8-9字节)
DWORDbfOffBits;//位图数据的起始位置,以相对于位图(10-13字节)
}BITMAPFILEHEADER;
2:
位图信息数据结构〔40个字节〕:
包含BMP图像的宽、高、压缩方法,以与定义颜色等信息;其结构定义如下:
typedefstructtagBITMAPINFOHEADER{
DWORDbiSize;//本结构所占用字节数(14-17字节)
LONGbiWidth;//位图的宽度,以像素为单位(18-21字节)
LONGbiHeight;//位图的高度,以像素为单位(22-25字节)
WORDbiPlanes;//目标设备的级别,必须为1(26-27字节)
WORDbiBitCount;//每个像素所需的位数,必须是1(双色),(28-29字节)
//4(16色),8(256色)或24(真彩色)之一
DWORDbipression;//位图压缩类型,必须是0(不压缩),(30-33字节)
//1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一
DWORDbiSizeImage;//位图的大小,以字节为单位(34-37字节)
LONGbiXPelsPerMeter;//位图水平分辨率,每米像素数(38-41字节)
LONGbiYPelsPerMeter;//位图垂直分辨率,每米像素数(42-45字节)
DWORDbiClrUsed;//位图实际使用的颜色表中的颜色数(46-49字节)
DWORDbiClrImportant;//位图显示过程中重要的颜色数(50-53字节)
}BITMAPINFOHEADER;
3:
调色板:
这个局部是可选的,有些位图需要调色板,有些位图不需要,比如真彩色图〔24位的BMP〕就不需要调色板;其颜色表结构定义如下:
typedefstructtagRGBQUAD{
BYTErgbBlue;//蓝色的亮度(值X围为0-255)
BYTErgbGreen;//绿色的亮度(值X围为0-255)
BYTErgbRed;//红色的亮度(值X围为0-255)
BYTErgbReserved;//保存,必须为0
}RGBQUAD;
颜色表中RGBQUAD结构数据的个数有biBitCount来确定:
当biBitCount=1,4,8时,分别有2,16,256个表项;当biBitCount=24时,没有颜色表项。
位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下:
typedefstructtagBITMAPINFO{
BITMAPINFOHEADERbmiHeader;//位图信息头
RGBQUADbmiColors[1];//颜色表
}BITMAPINFO;
4:
位图数据:
这局部内容根据BMP位图使用的位数不同而不同,在24位图中直接使用RGB,而其他的小于24位的使用调色板中颜色索引值。
位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。
位图的一个像素值所占的字节数:
当biBitCount=1时,8个像素占1个字节;
当biBitCount=4时,2个像素占1个字节;
当biBitCount=8时,1个像素占1个字节;
当biBitCount=24时,1个像素占3个字节;
Windows规定一个扫描行所占的字节数必须是4的倍数(即以long为单位),不足的以0填充。
biSizeImage=((((bi.biWidth*bi.biBitCount)+31)&~31)/8)*bi.biHeight;
●4.4.4BMP图片存储算法
BMP文件通常是不压缩的,所以它们通常比同一幅图像的压缩图像文件格式要大很多。
例如,一个800×600的24位几乎占据1.4MB空间。
因此它们通常不适合在因特网或者其它低速或者有容量限制的媒介上进展传输。
根据颜色深度的不同,图像上的一个像素可以用一个或者多个字节表示,它由n/8所确定〔n是位深度,1字节包含8个数据位〕。
图片浏览器等基于字节的ASCII值计算像素的颜色,然后从调色板中读出相应的值。
n位2n种颜色的位图近似字节数可以用下面的公式计算:
BMP文件大小约等于54+4*2n+〔w*h*n)/8,其中高度和宽度都是像素数。
需要注意的是上面公式中的54是位图文件的文件头,是彩色调色板的大小。
另外需要注意的是这是一个近似值,对于n位的位图图像来说,尽管可能有最多2n种颜色,一个特定的图像可能并不会使用这些所有的颜色。
由于彩色调色板仅仅定义了图像所用的颜色,所以实际的彩色调色板将小于。
由于存储算法本身决定的因素,根据几个图像参数的不同计算出的大小与实际的文件大小将会有一些细小的差异。
●4.4.5BMP图片的显示方法
bmp图片的显示方法主要有三种:
一是使用内存调用方法显示bmp图片。
我们通常所说的屏幕就是屏显,在将bmp调色板区写入计算机调色板和已经读取bmp文件图像存储区到内存的根底上,再从内存将数据读取给显存只需要进展一个内存复制操作就可以啦。
;二是直接从文件读取到屏幕显示bmp文件。
这种方法将通过显存显示bmp文件所需要的内存空间、读取数据到申请的空间、显示等多步任务简化成一步。
事实上也就是将读取文件数据到申请内存变到显示内存。
三是采用绘点的方法将图片的像素按照图片的文件的排列顺序一个个在屏幕上画出来。
本系统中采用的是第三种方法显示bmp图片。
具体实现代码如下:
voidview(char*fname)
{FILE*fp;
intmidx,midy;
intwidth,height,gd=DETECT,gm,i,j;
ColorBGR*buffer;
if((fp=fopen(fname,"rb"))==NULL)/*打开文件,并且判断文件是否存在*/
{cprintf("Can'tfindfile%s",fname);
exit
(1);
}
installuserdriver("Svga64k",return_SVGA64K_mode);/*对于svga64k必需执行该函数以安装BGI驱动*/
initgraph(&gd,&gm,"");/*执行TC默认的BGI初始化函数*/
fseek(fp,18,SEEK_SET);
fread(&width,4,1,fp);/*图象宽度*/
fread(&height,4,1,fp);/*图象长度*/
buffer=(ColorBGR*)malloc(width*sizeof(ColorBGR));/*为一行所有的像素的颜色开创空间,用来保存同一个宽度上的每个点的颜色值*/
fseek(fp,54,SEEK_SET);/*定位文件指针指向颜色存储区*/
midx=(getmaxx()-width)/2;
midy=(getmaxy()-height)/2;
for(j=height-1;j>=0;j--)
{fread(buffer,width*sizeof(ColorBGR),1,fp);/*读取该行像素的所有点的颜色*/
if(width%4)
{fseek(fp,(4-width%4),SEEK_CUR);/*宽度修正*/}
for(i=0;i{setrgbpalette(1026,buffer[i].r>>3,buffer[i].g>>2,buffer[i].b>>3);/*重设每个点的颜色*/
putpixel(midx+i,midy+j,0);/*画点*/
}
}
free(buffer);
fclose(fp);
sleep(3);
closegraph();
}
第五章总结
回顾整个开发过程,认识到软件系统的开发是一个综合性的工程,其开发过程的每一个阶段都要制定详细计划,特别是要了解系统的操作流程,可使系统的建设少走许多弯路,加快建设进度。
其次明确软件需求也是很重要的,在做每一个系统之前,你首先都要明确的知道要让该系统做什么。
只有明确了需求你才能进展下面的工作,另外,系统的设计是极其重要的,如果整体的设计出错如此后面所做的工作可能要全部返工。
经过本系统的开发让我了解到软件工程学对软件开发的重要作用。
更进一步的锻炼了我的编程思想,更深层次的熟悉软件开发的整个流程,也使我对C语言的强大与高深有了更进一步的认识。
为我以后在IT界的开展奠定了坚实的根底。
致谢
在三年的大学时光里,我学到了很多东西,尽管学的不是很精通,但起码也掌握了一门能在社会上立足的技术。
在此,我非常感谢学校教师对我的栽培和教诲。
参考文献
1、c游戏编程从入门到精通2、TurboC用户界面程序设计
3、C图形编程4、VESASVGA图形图像编程秘技