荔园在线
荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀
[回到开始]
[上一篇][下一篇]
发信人: Peter (小飞侠), 信区: Program
标 题: 微机交互式绘图时VGA图像的存储与恢复
发信站: BBS 荔园晨风站 (Wed Jan 27 17:51:43 1999), 转信
采用微机交互式绘图不仅能避免编程时碰到的难以确定座标的麻烦,
而且使操作者直接参与绘图的过程,可以如同在纸上作图一样来布局
自己的图形位置。而交互式绘制的图像必须能保存在磁盘文件中,并
能将已保存在磁盘中的图像重新显示在屏幕上,否则,交互式绘图技术
便会黯然失色。
本文介绍三种不但可有效地存取VGA整屏图像,而且能实现存取任
意大小图块的方法及其Turbo C函数。
方法之一
C库函数中有getimage()与putimage()对图块复制的操作函数,但
描述图块的总字节数大小不能超过64K字节,而存储16色、640×480标
准VGA整屏图像需达150K字节之多。一种方法是将整帧图分为三个图
块分别存储于磁盘文件中。即使如此,用getimage()库函数之前仍需
开辟50K以上的缓存区,所需占用的内存仍是较大的,尤其是在编制大
型交互式绘图软件时,更会显得内存紧张,甚至造成死机现象。为了节
省缓存可采用将整屏图切割成更小的图块的方法,如分成480行块,这
样仅需要324字节的缓存空间。但如此存储每块图形又需比描述图像
信息实际的320字节多4个字节,共需多占480×4即1920字节磁盘空间
。能否进一步省去这些多余的字节呢?答案是肯定的。
经探索发现getimage()函数开辟的缓存数组的第1、2个元素是描
述图块的宽度x,第3、4个元素是描述图块的高度y,设图块的左上角与
右下角的坐标分别是(x1,y1)和(x2,y2),缓存数组为buf[],则:
x=buf[0]+buf[1]*256;
y=buf[2]+buf[1]*256;
对于存储480行图块的数组,前4个元素均分别为127,2,0,0,因而
不必存储,再现图像时在数组前4个元素中一一赋予这4个相应数值则
可。根据上述原理用Turbo C编制整屏存图与取图的函数save-scrpic
-1()与loadscrpic-l()的源程序如下(头文件略):
save-scrpic-l(char *pic-name) {FILE *fp;
register unsigned int i,j;
char buf[324];
fp=fopen(pic-name,"wb");
for(j=0;j<480;j++)
{getimage(0,j,639,j,buf);
for(i=4;i<324;i++)
fputc(buf[i],fp);
}
fclose(fp);
}
loadscrpic-l(char *pic-name)
{FILE *fp;
register unsigned int i,j;
char buf[324]=(127,2,0,0);
fp=fopen(pic-name,"rb");
for(j=0;j<480;j++)
(for(i=4;i<324;i++)
buf[i]=fgetc(fp);
putimage(0,j,buf,COPY-PUT);
}
fclose(fp);
}
源程序中的参数*pic-name为存储图像的磁盘文件名。
类似地可以编制出存储与再现任意大小图块的C函数save-subpic
-1()与loadsubpic-1( ),不同的是存储图块的磁盘文件必须先用前4
个字节描述图块的宽度x=x2-x1和高度y=y2y1。由于图块的恢复可以
任意指定左上角,不必与原位置相同,故不必保存原图块的左上角坐标
( x1,y1)与右下角的坐标(x2,y2)。
save-subpic-1(int x1,int y1,int x2,int y2,char *pic-name
)
{FILE *fp;
register int i,j;
int x;
unsigned int size;
char buf[324];
for(i=4;i<324;i++)
buf[i]=0;
x=x2-x1;
fp=fopen(pic-name,"wb");
fputc(x%256,fp);
fputc(x/256,fp);
fputc(y2y1)%256,fp);
fputc(y2y1)/256,fp);
for(j=y1;j<y2+1;j++)
{getimage(x1,j,x2,j,buf);
for(i=4;i<(4+(x+1.5)/2);i++)
fputc(buf[i],fp);
}
fclose(fp);
}
loadsubpic-1(int x1,int y1,char *pic-name)
{FILE *fp;
register int i,j;
int x,y;
char buf[326];
for(i=4;i<324;i++)
buf[i]=0;
fp=fopen(pic-name,"rb");
for(i=0;i<2;i++)
{buf[i]=fgetc(fp);
buf[i+2]=0;
}
x=buf[0]+buf[1]*256;
y=fgetc(fp)+fgetc(fp)*256;
for(j=y1;j<=y1+y;j++)
{for(i=4;i<(4+(x+1.5)/2);i++)
buf[i]+fgetc(fp);
putimage(x1,j,buf,COPY-PUT);
}
fclose(fp);
}
将上述源程序中的COPY-PUT换成XOR-PUT、OR-PUT、NOT-PUT则可
实现将磁盘中存储的图像与原屏幕图像异或、或、反相叠加。
方法之二
另一种方法则是利用C中读点与写点的函数来实现图形的存储与
再现,此法存取图像速度慢些,但不需占用内存,且兼容性好,可靠性高
。
对于16色的图像,存储每个象素点需要4个位,即每个字节可描述
两个点的颜色值,第1个点在高4位,第2个点在低4位。故存图的磁盘文
件每字节的值c应为读取第1点的颜色值左移4 位后再加上同一行相邻
第2点的颜色值:
c=(getpixel(i,j)<<4)+getpixel(i+1,j);
而图像的恢复则相反,从磁盘文件中每读取1个字节后,右移4位则
为第1点dot1的颜色值,而同一行相邻第2个点的颜色值dot2必须将该
字节的高4位值屏蔽,即将该字节与二进制000 01111(十进制数为15)
相与:dot2&15。用此法编写的全屏幕图像存取的c函数如下:
save-scrpic-2(char *pic-name)
{FILE *fp;
register int i,j;
fp=fopen(pic-name,"wb");
for(j=479;j>=0;j--) /*从底到顶*/
for(i=0;i<639;i+=2) /*从左到右*/
fputc((getpixel(i,j)<<4)+getpixel(i+1,j),fp);
fclose(fp);
}
loadscrpic-2(char *pic-name)
{FILE *fp;
register int i,j;
unsigned char dot1,dot2;
fp=fopen(pic-name,"rb");
for(j=479;j>=0;j--) /*从底到顶*/
for(i=0;i<639;i+=2) /*从左到右*/
{dot1=dot2=fgetc(fp);
if(dot1>>=4 putpixel(i,j,dot1);
if(dot2&=15) putpixel(i+1,j,dot2);
}
fclose(fp);
}
之所以图像阵列的存取采用从底到顶而不是从上到下的顺序是为
了与BMP图像文件格式相兼容之故。下面是加上存储16色BMP图像块文
件头的源程序。
save-bmp(int x1,int x2,int y1,int y2,char *pic-name)
{unsigned char bmp-head[118]=
{66,77,118,88,2,0,0,0,0,0,
118,0,0,0,40,0,0,0,128,2,
0,0,224,1,0,0,1,0,4,0,
0,0,0,0,0,0,0,0, 0,0,
0,0,0,0,0,0,0,0, 0,0,
0,0,0,0,0,0,0,0,128,0,
0,0,0,128,0,0,128,128,0,0,
0,0,128,0,128,0,128,0,0,128,
128,0,192,192,192,0,128,128,128,0,
255,0,0,0,0,255,0,0,255,255,
0,0,0,0,255,0,255,0,255,0,
0,255,255,0,255,255,255,0);
FILE *fp;
int i,j,x,y,n,dot1,dot2;
x=x2-x1+1;
y=y2y1+1;
bmp_head[18]=x%256;
bmp_head[19]=x/256;
bmp_head[22]=y%256;
bmp_head[23]=y/256;
if(x%8==0) n=x;
else n=x+8-x%8;
fp=fopen(pic_name,"wb");
fwrite(bmp_head,118,1,fp);
for(j=y2;j>=y1;j--)
(for(i=x1;i<=x1+n;i+=2)
(dot1=getpixel(i,j);
dot2=getpixel(i+1,j);
if(i>=x1+x) dot1=dot2=0;
fputc((dot1<<4)+dot2,fp);
}
}
fclose(fp);
}
方法之三
方法三则是直接对显示器缓存区操作,因而运行速度较快,但与硬
件有关。标准VGA整屏图像有640×480象素点,显示内存被组织成4个
可独立寻址的存储位平面,且这4个存储位平面所占的地址空间相同,
起始地址均为OXA0000H,屏幕上的一个象素点由蓝、绿、红、灰(亮度
)4层图像位平面中各1位组合而成,可组合成16种颜色,每个位平面的1
个字节代表连续8个点的颜色状态。整个屏幕需占地址相同的4个位平
面中各38400个字节,而每行需占4个位平面中地址相同的各80个字节
。因而屏幕上象素点(i,j)此时相对于显示内存起始地址的偏移量为j
*80+i/8。
要访问显示内存需对寄存器正确操作。I/O端口值为3CEH的是图
形地址寄存器,3CFH是图形数据寄存器。赋予3CEH不同的值,可选择不
同的图形数据寄存器作为当前活动寄存器。若赋予3CEH值为04时,便
选择了读出彩色图像页面选择寄存器(端口值为3CFH),而置3CFH为0、
1 、2、3时便决定了代码为0、1、2、3的4层位图像页面中的对应位
平面来读。据此可编制出存储整屏图像及任意大小图块的函数save-s
crpic-3()及save-subpic-3()。
在VGA屏幕上恢复显示图形,关键在于对定序器输出寄存器的正确
控制。定序器地址寄存器的端口值为3C4H;定序器数据寄存器的端口
值为3C5H。置3C4H端口值为不同的值可以选择不同的定序器数据寄存
器作为当前活动寄存器,当赋予端口3C4H的值为02时便选择了映射屏
蔽寄存器(端口值仍为3C5H)。
对端口3C5H分别置1、2、4、8时,则选择了蓝、绿、红、灰(亮度
)四个颜色显示页面来写。据此可编写出将存储于磁盘中的图像写入
显示缓存区的函数loadscrpic-3()和loadsub pic-3()。
save-scrpic-3(char *pic-name)
{register unsigned i;
char far *ptr=(char far *)MK-FP(0xa000,0x0000);
FILE *fp;
fp=fopen(pic-name,"wb");
for(i=0;i<38400;i++)
{outportb(0x3ce,4);
outportb(0x3cf,0);
fputc(*ptr,fp);
outporrb(0x3cf,1);
fputc(*ptr,fp);
outportb(0x3cf,2);
fputc(*ptr,fp);
outportb(0x3cf,3);
fputc(*prt,fp);
ptr++;
}
fclose(fp);
outportb(0x3ce,4);
outportb(0x3cf,0);
}
loadscrpic-3(char *pic-name)
{register unsigned i;
char far *ptr=(char far *)MK-FP(0xa000,0x0000);
FILE *fp;
fp=fopen(pic-name,"rb");
for(i=0;i<38400;i++)
(outportb(0x3c4,2);
outportb(0x3c5,1);
*ptr=fgetc(fp);
outportb(0x3c5,2);
*ptr=fgetc(fp);
outportb(0x3c5,4);
*ptr=fgetc(fp);
outportb(0x3c5,8);
*ptr=fgetc(fp);
ptr++;
}
fclose(fp);
outportb(0x3c4,2);
outportb(0x3c5,0xf);
}
同样,图块的存取须在磁盘文件中前4个字节记录图块的宽度和高
度。限于篇幅,略去该方法图块存取的源程序。
讨论
1.本文三种方法均可有效地存取VGA整屏图像,也可存取任意大小
的图块。文中提供的源程序可直接用作开发交互式绘图软件图像存取
的功能模块。
2.方法三的运行速度最快的,方法一次之,方法二较慢;方法一和
方法二存于磁盘中的图像再现时可与原屏幕图像叠加;方法二和方法
三不耗缓存,方法一也仅需324字节的缓存;方法二存储的图像便于放
大、缩小、旋转等变化后恢复于屏幕。
3.本文存取图块的方法不消耗缓存,不受64K字节的限制,可方便
用于交互式绘图时(利用虚拟盘或硬盘)保存与恢复弹出或下拉菜单前
的屏幕图像。
4.方法二存取图像阵列的方式与未压缩的BMP图像阵列的格式是
相同的,因而用此法存储的图像文件加上相应BMP图像的文件头即成BM
P图像文件。这样就可实现用C绘制的科技图形用此法存盘而被WINDOW
S下的图形软件或图文编辑软件所调用。
--
--
※ 来源:.BBS 荔园晨风站 bbs.szu.edu.cn.[FROM: 192.168.1.3]
[回到开始]
[上一篇][下一篇]
荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店