C 图形设计
转:
还有一个比较好的画图库:easyx,http://www.easyx.cn/
第12章 图形与音乐设计【本章要点】 本章主要介绍了C语言高级应用中的图形和音乐。图形设计部分主要包括图形模式设置,图形方式下基本图形绘制,图形方式下文本输出及动画设计。音乐设计部分介绍利用扬声器(PC喇叭)和声卡技术设计音乐程序的方法。本章重点掌握图形方式下基本图形绘制和文本输出内容。难点在于涉及硬件及汇编知识的声音音乐设计,此部分对于利用C语言进行动画音乐设计的学习者很有帮助。 12.1 图形设计12.1.1 图形设计基础1. Turbo C与图形接口C语言具有相当强的图形处理能力,支持CGA、MCGA、EGA、VGA和IBM8514等图形显示器。一般的IBM PC型显示器可以在两种基本视频模式下工作,一是文本模式,另一种是图形模式。文本模式即常见的命令行方式,屏幕上可以显示的最小单位是字符。常用的VGA显示器,可以显示80列25行文本。图形模式下,屏幕上每一个可以控制的单元叫做像素(pixel),它是组成图形的基本元素,一般称为点。通常把屏幕上所包含的像素的个数叫做分辨率。分辨率越高,显示的图形越细致,质量越好。VGA显示器的分辨率为640×480,即VGA在水平方向上有640个像素点,垂直方向上有480个像素点。 在图形模式下,屏幕上每个像素的显示位置用点坐标系来描述。在这种坐标系中,屏幕左上角坐标原点为(0,0),水平方向为X轴,自左向右递增,垂直方向为Y轴,自上而下递增。如图12.1所示。分辨率不同,水平方向和垂直方向的点数也不一样即maxx、maxy数值不同。
在TC中,坐标数据可以用两种形式给出,一是绝对坐标,另一是相对坐标。绝对坐标的参考点是坐标系原点(0,0),x和y只能取规范内的正整数,其坐标值在整个屏幕范围内确定。相对坐标是相对“当前点”的坐标,所以其坐标的参考点是当前点。在相对坐标中,x和y的取值是相对于当前点在x方向和y方向上的增量,这个增量可以是正的,也可以是负的。 2.Turbo C图形库函数Turbo C 具有70多个图形库函数,因此其图形功能极为丰富。所有这些库函数均在头文件“graphics.h”中定义,所以,凡是在程序中要调用这些图形函数,都必须在程序文件的开头写上文件包含命令“include<graphics.h>”。 Turbo C图形函数库中提供的函数包括7类: (1)图形系统控制函数 closegraph()——关闭图形状态,返回文本状态 detectgraph()——测试硬件,决定使用那一个图形驱动器和使用那种图形方式 graphdefaults()——重置所有图形系统变量为默认的设置 getgraphmode()——返回当前的图形方式 initgraph()——初始化图形系统,将硬件设置成图形方式 restorecrtmode()——恢复initgraph之前的屏幕方式 setgraphbufsize()——声明内部图形缓冲区的大小 setgraphmode()——选择指定的图形方式,清除屏幕,恢复所有的默认值 (2)画线与填充函数 arc()——画一个圆弧 circle()——画一个圆 drawpoly() ——画一个多边形 ellipse() ——画一个椭圆 line() ——画一个直线 lineto()——画一个从当前图形坐标位置开始到坐标(x,y)处的直线 moveto() ——坐标移到(x,y)处。 moverel() ——将当前坐标移动一个相对距离 rectangle() ——画一个矩形 fillpoly()——填充一个多边形 pieslice()——画并填充一个扇形 bar()——画并填充一个二维条形 bar3d()——画并填充一个三维条形 setfillstyle()——设置填充图案和颜色 setlinestyle()——设置当前画线宽度和样式 getarccords()——返回上次调用arc和ellipse的坐标 getaspectratio()——返回当前图形方式的长宽比例 getlinesettings()——返回当前的画线式样、画线模式和画线宽度 getfillpattern()——返回用户定义的填充图案 getfillsettings() ——返回当前填充图案和填充颜色信息 (3)管理屏幕和视口函数 cleardevice()——清除屏幕 setactivepage()——设置图形输出活动页 setvisualpage()——设置可见图形页面 clearviewport()——清除当前视口 getviewsettings()——返回关于当前视口的信息 setviewport()——为图形的输出设置当前输出视口 getimage()——将指定区域的位图像存入内存 imagesize()——返回保存屏幕的一个矩形区域所需的字节数 putimage()——将用getimage()保存的位图像存入内存 getpixel()——取得(x,y)处的像素颜色 putpixel()——在(x,y)处画一个像素点 (4)图形方式下的字符输出函数 gettextsettings()——返回当前字体、方向、大小和对齐方式 outtext()——在当前位置输出一个字符串 outtextxy()——在指定位置输出一个字符串 registerbgifout()——登录连接进来的或用户装入的字体文件*.BGI settextjustify()——设置outtext和outtextxy所有的对齐方式编码值 settextstyle()——设置当前字体、式样和字符放大因子 setusercharsize()——设置当前矢量字体的宽度和高度比例 textheight()——返回以像素为单位的字符串高度 textwidth()——返回以像素为单位的字符串宽度 (5)颜色控制函数 getbkcolor()——返回当前背景颜色 getcolor()——返回当前画线颜色 getmaxcolor()——返回当前图形方式下最大的可用颜色值 getpalette()——返回当前调色板及其尺寸 setallpalette()——按指定颜色改变所有调色板的颜色 setbkcolor()——设置当前背景颜色 setcolor()——设置当前画线颜色 setpalette()——按参数所指定的颜色改变一个调色板的颜色 (6)图形方式下的错误处理函数 grapherrormsg()——返回指定的errorcode错误信息字符串 graphresult()——返回上一次遇到问题的图形操作错误代码 (7)状态查询函数 getaspectratio()——返回图形屏幕的长宽比 getmaxx()——返回当前x的分辨率 getmaxy()——返回当前y的分辨率 getx()——返回当前像素x的坐标 gety()——返回当前像素y的坐标 3.Turbo C绘图的基本步骤(1)设置图形模式 在编制图形程序时,首先要对使用的图形系统进行初始化,即确定图形显示适配器的驱动程序类型,要采用的图形显示模式,以及该适配器驱动程序的存储路径。注意此处所选图形显示适配器驱动程序一定要支持所选用的图形显示模式,否则将出错。Turbo C提供图形方式初始化函数initgraph()。 (2)绘制图形 在图形方式下使用各种绘图函数绘制图形,这是图形设计的第二步。 如circle(100,200,50)就可以在点(100,200)处绘制一个半径为50的圆。 (3)关闭图形方式 closegraph()函数用来关闭图形方式返回文本方式,这是图形设计的第三步。 【例12.1】使用Turbo C图形系统的一个简单实例。 #include<graphics.h>//调用图形库函数 #include<conio.h> main() { int gdrive=DETECT,gomde; int x_max,y_max; initgraph(&gdriver,&gmode,”c:\\tc”); /*初始化图形方式*/ x_max=getmaxx(); y_max=getmaxy(); moveto(x_max/2,0); lineto(0,y_max); lineto(x_max,y_max); lineto(x_max/2,0); getch(); closegraph(); /*关闭图形方式*/ } 12.1.2 图形模式设置图形模式设置即所谓的“图形方式初始化”,在一般缺省的情况下,Turbo c 编辑屏幕为80列25行的文本方式,此时所有图形函数均不能操作,因此在使用图形函数绘图之前,必须将屏幕显示适配器设置为一种图形模式。而在绘图完毕后,要关闭图形方式返回到文本方式,TC 2.0提供了14种函数对图形模式系统进行控制和管理。 1.图形方式初始化图形方式初始化通过函数initgraph来完成。其调用格式为: initgraph(*gdriver,*gmode,*path); 函数initgraph通过从磁盘装入一个图形驱动程序来完成初始化图形系统,并将系统设置为图形方式,其中3个参数的含义如下。 (1)gdriver是一个枚举型变量,它属于显示器驱动程序的枚举类型: Enum graphics_driver{DETECT,CGA,MCGA,EGA,EGA64,EGAMONO,IBM8514, HERCMONO,ATT400,VGA,PC3270}; gdriver也可表示成一个整型值数据,它与枚举成员的对应关系为:DETECT为0,CGA为1,以此类推。使用DETECT,由系统自动检测图形适配器类型,同时装入相应的驱动程序,并将其最高的显示模式作为当前的显示模式,如下面所示: EGA 1(640×350,16色,即EGAHI) VGA 2(640×480,16色,即VGAHI) (2)gmode是一个整型值,用来设置图形显示模式,不同的图形驱动程序有不同的图形显示模式,即使是同一个图形驱动程序下,也有几种图形显示模式。图形显示模式决定了显示的分辨率、可同时显示颜色的多少,调色板的设置方式以及存储图形的页数。常用的几种显示模式如表12.1所示。 表12.1 几种常用的显示模式
(3)path是一个字符串,用来指定图形驱动程序所在的路径(即BGI的存储路径)。如果驱动程序就在用户当前目录下,则该参数可以为空字符串,否则应该给出具体的路径。一般情况下,turbo c 安装在c盘的tc目录中,该路径为C:\TC,如果写在参数中则为”C:\\TC”。 例如,在程序中使用VGA图形驱动程序,图形显示模式为VGAHI,即VGA高分辨率图形模式,分辨率为640×480,则initgraph函数的调用方式如下: int gdriver=VGA,gmode=VGAHI; initgraph(&gdriver,&gmode,”c:\\tc”); 也可以用整型常数代替符号常数,例如: int gdriver=9,gmode=2; initgraph(&gdriver,&gmode,”c:\\tc”); 上面两种图形模式设置结果是等价的。 2.关闭图形方式在运行图形程序绘图结束后,要回到文本方式,以进行其他工作,这时应关闭图形方式。关闭图形方式要调用的函数closegraph。其调用格式为: closegraph(); 其作用是释放所有图形系统分配的存储区,恢复到调用initgraph之前的状态。 为了不关闭图形系统,使相应适配器的驱动程序和字符集仍驻留在内存,但又回到原来所设置的模式,可使用恢复工作模式函数restorecrtmod(),该函数常和另一设置图形工作模式函数setgraphmode交互使用,使显示器工作方式在图形和文本方式之间来回切换,增强了程序编辑的灵活性。 12.1.3 基本图形绘制图形由点、线、面组成,图形的绘制使用基本绘图函数来完成的。Turbo C提供的图形函数参照第一小节,本部分主要介绍几类基本图形的绘制方法。 1.画点画点函数如下: putpixel(int x,int y,intcolor); 它表示在指定的x,y位置画一个点,点的显示颜色由设置的color值决定,关于颜色的设置,将在设置颜色函数中介绍。 如:putpixel(10,10,WHITE);/*在(10,10)处画一白点*/ 2.画直线(1)line函数 line(int x1,int y1,int x2,int y2); line函数用于在指定两点之间画一条直线段,参数x1,y1,x2、y2使用绝对坐标,(x1,y1)和(x2,y2)分别为直线的两个端点坐标。用line函数画直线时,当前点位置不变。 (2)lineto函数 lineto(int x,int y); lineto函数用于从当前点位置到指定位置(x,y)画一条直线,并改变当前点的位置。所以画一条直线的同时,当前点的位置也移到了指定点,即直线的终点。 (3)moveto函数 moveto(int x,int y);//将当前点移动到(x,y)。 (4)linerel函数 linerel(int dx,int dy); linerel函数使用相对坐标画直线。其功能是从当前点位置开始画线到指定点位置,指定点位置的坐标不是以绝对坐标的形式给出的,而是以其相对于当前点位置的坐标增量给出的。假设当前点位置坐标是(x,y),则“linerel(dx,dy)”等效为“lineto(x+dx,y+dy)”。 (5)moverel函数 moverel(int dx,int dy); 该函数的功能与moveto函数相似,但他使用的是相对坐标。用于将当前点位置在x和y方向上分别移动增量dx和dy。 【例12.2】绘制直线 #include "graphics.h" void main() { int gd=DETECT,gm; initgraph(&gd,&gm,"c:\\tc"); cleardevice(); printf("\n Draw lines with function 'line'."); line(160,120,480,120); line(480,120,480,360); line(480,360,160,360); line(160,360,160,120); getch(); cleardevice(); printf("\n Draw lines with function 'lineto'."); moveto(160,120); lineto(480,120); lineto(480,360); lineto(160,360); lineto(160,120); getch(); cleardevice(); getch(); printf("\n Draw lines with function 'linerel'."); moveto(160,120); linerel(320,0); linerel(0,240); linerel(—320,0); linerel(0,—240); getch(); closegraph(); } 3.画矩形和条形画矩形函数rectangle将画出一个矩形框,而画条形函数bar将以给定的填充模式和填充颜色画出一个条形图来。 (1)画矩形函数 rectangle(int x1,int y1,int x2,int y2); 该函数将以(x1,y1)为左上角,(x2,y2)为右下角画一个矩形框。 (2)画条形函数 bar(int x1,int y1,int x2,int y2); 该函数将以(x1,y1)为左上角,(x2,y2)为右下角画一实形条状图,没有边框,图的颜色和填充模式可以设定。如果没有设定,则可以使用缺省模式。 【例12.3】绘制矩形和条形图 #include "graphics.h" main() { int gd=DETECT,gm,x; initgraph(&gd,&gm,"c:\\tc"); cleardevice(); rectangle(100,20,200,50); bar(100,80,150,180); getch(); closegraph(); } 4.画椭圆、圆和扇形图形(1)画椭圆函数 ellipse(int x,int y,int stangle,int endangle,int xradius,int yradius); 该函数将以(x,y)为中心,以xradius和yradius为x轴和y轴半径,从起始角stangle开始到endangle角结束,画一椭圆线。当stangle=0,endangle=360时,则画出的是一个完整的椭圆,否则画出的将是椭圆弧。 (2)画圆函数 circle(int x,int y,int radius); 该函数将以(x,y)为圆心,radius为半径画个圆。 (3)画圆弧函数 arc(int x,int y,int stangle,int endangle,int radius); 该函数将以(x,y)为圆心,radius为半径,从stangle为起始角开始,到endangle为结束角画一个圆弧。 在画椭圆和画圆弧函数以及后面的函数中,提到有关于角的概念在Turbo C中是这样规定的:屏幕X轴方向为0,当半径从此处逆时针旋转时,则依次是90°、180°、270°,是360°时,则和x轴正向重合,即旋转了一周。 (4)画扇形函数 piestilice(int x,int y,int stangle, int endangle,int radius); 该函数以(x,y)为圆心,radius为半径,从stangle为起始角,endangle为结束角,画一扇形图,扇形图的填充模式和填充颜色可以预先设定,否则以缺省模式进行。 【例12.4】 #include "graphics.h" main() { int gd=DETECT,gm,x; initgraph(&gd,&gm,"c:\\tc"); cleardevice(); ellipse(320,100,0,360,75,50); circle(320,220,50); pieslice(320,340,30,150,50); ellipse(320,400,0,180,100,35); arc(320,400,180,360,50); getch(); closegraph(); } 12.1.4 图形属性设置1. 屏幕颜色控制图形模式的屏幕颜色设置分为背景色的设置和前景色的设置。在Turbo C中分别用下面两个函数来实现。 设置背景色: setbkcolor(int color); 设置作图色: setcolor(int color); 其中,color为图形方式下颜色的符号常数或数值,对EGA、VGA显示适配器,有关的颜色符号常数及数值之间的对应关系如表12.2。 表12.2 颜色符号常数及数值之间的对应关系
【例12.5】在蓝色背景屏幕窗口画一个红色边线的圆。 #include <graphics.h> main() { int gd=DETECT, gm; initgraph(&gd,&gm,"c:\\tc"); cleardevice(); setbkcolor(1); setcolor(4); circle(200,200,100); getch(); closegraph(); } 对于CGA适配器,背景色可以为表12-2中的16种颜色之一,但前景色由不同的调色板决定,共有四种调色板,每种调色板上有四种颜色可以选择。不同调色板所对应的颜色如表12.3所示。 12.3 CGA的调色板号与对应的颜色值
【例12.6】 #include <graphics.h> main() { int gd=CGA; int gm=CGAC0; initgraph(&gd,&gm,"c:\\tc"); cleardevice(); setcolor(1); //设置0号调色板的1号颜色值,即绿色 line(0,0,100,100); getch(); setbkcolor(BLUE); /*也可以用setbkcolor(1)*/ line(20,40,150,150); getch(); setcolor(0); //设置0号调色板的0号颜色值,即作图色与背景同色,画线不被显示 line(60,120,220,220); getch(); closegraph(); } 2.设置线条类型设置线条类型采用函数setlinestyle来实现。该函数用于设置当前绘图所用的线型和宽度。其调用格式为: setlinestyle(int sty,int pat, int b); 该函数所用的3个参数含义如下: (1)sty用来定义所画直线的类型。包括SOLID_LINE、DOTTED_LINE、CENTER_LINE、DASHED_LINE和USERBIT_LINE,其对应的数值依次为0-4,含义为实线(缺省)、点虚线、点划线、破折线和用户自定义类型。 (2)pat用于用户自定义直线的类型,如果sty值取0-3系统预定义的线型,则pat不起作用,可赋值为0。如果sty取值为4时,用户可自定义线型。 Pat参数是一个16位二进制码,每一位(bit)表示一个像素。某一位置1时表示直线上相应位置显示,置0时表示不显示。例如,1111 1111 1111 1111,16位全置1,因此是画一条实线,而1010 10 10 10 10,隔位置1,因此画一条点线。在实际编程时,一般将16位二进制,转换为4位十六进制数,故上面两个例子可分别转换为FFFF和AAAA,函数调用方法为“setlinestyle(4,0xAAAA,1)”,用这种方法,可以根据需要定义各种线型。 (3)b表示所画线的粗细,以像素为单位。可取NORM_WIDTH和THICK_WIDTH,对应数值为1和3,含义是1个像素宽和3个像素宽。 【例12.7】 #include "graphics.h" main() { int i,j,c,x=50,y=50,k=1; int gd=DETECT,gm; initgraph(&gd,&gm,"c:\\tc"); cleardevice(); setbkcolor(9);/*设置背景颜色为浅蓝*/ setcolor(4);/*设置画线颜色为红色*/ for(j=1;j<=2;j++) { for(i=0;i<4;i++) { setlinestyle(i,0,k); line(50,50+i*50+(j—1)*200,200,200+i*50+(j—1)*200); rectangle(x,y,x+210,y+80); circle(100+i*50+(j—1)*200,240,100); } k=3; x=50; y=250; } getch(); closegraph(); } 本程序用于演示系统预定义的4种线型。首先初始化图形方式,清屏,设置背景色和前景色,在第一个for循环中设置两种不同的线型宽度,在第2个for循环中设置4种不同的线型,并分别绘制直线、矩形和圆。可以看出直线的线型和线宽均发生变化,而矩形和圆仅线宽发生了变化。 3.设置填充类型和填充颜色填充即用规定的颜色和图模填满一个封闭的图形。 (1)设置填充模式和填充颜色函数setfillstyle,其调用格式: setfillstyle(int pattern,int color); 其中,参数pattern用于指定填充模式。系统有13种预定义的填充模式见表12.4。参数color用于指定填充颜色。 12.4 填充模式及含义
(2)常用的填充函数。 ①bar(int x1,int y1,int x2,int y2)函数,以(x1,y1)为左上角,(x2,y2)为右下角画矩形窗口并填充。 ②fillellipse(int x,int y,int rx,int ry)函数,以(x,y)为中心坐标,rx、ry分别为x轴和y轴半径,画椭圆并填充。 ②sector(int x,int y,int stangle,int endange,int rx,int ry),以(x,y)为圆心,rx、ry分别为x轴和y轴半径,从起始角stangle开始到endangle角结束,画椭圆扇形,并填充。 【例12.8】 #include "graphics.h" main() { int gd=DETECT,gm; initgraph(&gd,&gm,"c:\\tc"); cleardevice(); setfillstyle(LINE_FILL,YELLOW); bar(0,0,30,30); fillellipse (100,100,50,50); sector(200,200,30,150,50,50); getch(); closegraph(); } (3)任意封闭图形的填充 floodfill函数可以实现对任意封闭图形区域的填充操作,其调用格式为: floodfill(int x,int y,int bcolor); 参数(x,y)指位于填充区域内任意一点坐标,以该点作为填充起始点。bcolor为填充区域边界的颜色。例如: setcolor(RED); circle(320,240,150); setfillstyle(SOLID_FILL,GREEN); floodfill(320,240,RED); 该段程序的作用是,用红色画一个圆,然后用绿色色块填充该圆。可以看出任意封闭图形的填充步骤为:先确定填充图形边界(比如例题中的画圆语句),然后用setfillstyle函数确定填充模式和颜色,最后用floodfill函数填充图形区域。 12.1.5 图形方式下文本的输出Turbo C 提供了专门用于在图形模式下输出文本的函数。 1.文本输出函数outtext(char far *textstring);——在当前位置输出字符串指针textstring所指的文本。 settextjustify(horiz,vert); ——定位输出字符串的对齐方式,其中参数horiz和vert的取值见表12.5。 表12.5 文本定位输出字符串时的对齐方式
例如: settextjustify(LEFT_TEXT,0); outtextxy(120,20,s);//s代表一个字符串 程序段的含义是:输出字符串s,s的位置水平方向以坐标(120,20)为中心,垂直方向以(120,20)为底线。 2.定义文本字型settextstyle(font,direction,charsize); ——设置文本字型、方向和大小,其中三个参数都为整型,取值见表12.6,12.7。 表12.6 font和direction取值
例如:settextstyle(DEFAULT_FONT,HORIZ_DIR,2); ——设置以默认字符型水平方向输出16×16点阵字。 表12.7 charsize取值
【例12.9】 #include "graphics.h" main() { int gd=DETECT,gm; char s[30]; initgraph(&gd,&gm,"c:\\tc"); settextjustify(CENTER_TEXT,CENTER_TEXT); settextstyle(TRIPLEX_FONT,HORIZ_DIR,6); sprintf(s,"TEXT in a box"); outtextxy(200,50,s); getch(); closegraph(); } | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||