SVGA 图像处理
SVGA 彩色图形卡是一种超级 VGA 卡,它不仅具有 640×480×16 色图像显示模式,
而且具有 640×480×256 色图像显示模式。Microsoft C/C++ 提供了丰富的图形库函数
,尤其是提供了对 SVGA 卡所能设置的高分辨率图像模式的支持,利用丰富的图形库函数
进行组合,就可以完成各种需要的功能。例如图像处理,动画编程,界面制作等。这一点
对编程者来说无疑是十分方便的。然而遗憾的是许多图形库函数在一些特定的显示模式(
如-VERS256COLOR(0x0101)方式(640×480×256)等 256 色模式)下却无法正常工作,例
如使用例程-getimage()和-putimage()时常会出现死机和不能正常工作(出现雪花或不进行任
何操作)等现象。用-grstatus()函数检测调用函数的状态时,返回图形错误或警告信息,常
见的有图形错误(-1)和不支持请求的视频方式(-2)等,而这些函数在 VGA 下工作正常。根
据 VESA 图形标准,在图像模式下,SVGA 的 Video buffer(视频缓冲区)是顺序的链结构,
且图像数据是按行序顺序存放的,一个像素(屏幕上的一个点)用存储器的一个字节(256 色)
表示。视频存储器按字节连续寻址,与主机内存采用映射方式通讯,一次只能读写 64KB
的视频存储器,通过改变段偏移量(I/O 操作)来寻址不同的段,即实现对全部视频存储器
的操作。同时,直接访问 SVGA 的寄存器进行读写操作,充分利用硬件的支持可以大大加
快图形的处理速度。实践表明,其运行速度明显优于图形库中提供的函数(以-getimage()和
-putimage()为例快 30 倍)。笔者通过对视频存储器(Video buffer)的直接访问实现了 256 色
图像显示模式下图像块的读写功能。下面附上在 VESA 标准的 0x0101(256)图像显示模式
下-getimage()和-putimage()两个函数的源程序,该源程序是用 Microsoft C/C++ 编写的
。这两个函数在 Compaq 486 及兼容机上运行通过。-getimage()和-putimage()两个函数的
参数类型说明及意义与 Microsoft C/C++ 中相应函数的参数类型说明及意义相同。/*
将图像存储到缓冲区中 */void-getimage256(x1,y1,x2,y2,image)short x1,y1,x2,y2;char-
huge *image;{char-far*buf,-huge *q;long u;short m,n,i,j,block;m=abs(x2-x1)+1;n=abs(y2-
y1)+1;(short)*image=m;(short)*(image+2)=n;/* 保留图像的高度与宽度
*/q=image+4;u=min(x1,x2);u+=min(y1,y2) * 640L;block=(short)(u/65536L);u-
=block*65536L;/* 计算偏移量 */-FP-SEG(buf)=0xA000;-FP-OFF(buf)=u;-outp(0x3c4,14),-
outp(0x3C5,block^2);/* 设置页寄存器 */for (i=0; i<n; i++, q+=m) {/* 行循环 */-
memcpy(q, buf, m);u+=640;if(u<65536L) buf+=640;else {/* 当一行不在同一段时 */u-
=65536L;-FP-SEG(buf)=0xA000;-FP-OFF(buf)=0;block++;-outp(0x3C4,14);-
outp(0x3C5,block^2);if(m>640-u)-memcpy(q+640-u,buf,(size-t)(m-640+u));-FP-
OFF(buf)=u;}}}/* 在缓冲区中搜索图像 */void-putimage256(x,y,image,action)short
x,y,action;/* 参数 action 表示图像写方式 */char-huge * image;{char-far *buf,-
huge*q;long u;short m, n, j, i, block, mm;-memcpy(&mm, image, 2);if ((x+mm)>640)
m=640-x;else m=mm;-memcpy(&n, image+2, 2);if (y+n>480) n=480-n;/* 取图像的高度
和宽度,并进行边界处理 */q=image+4;u=x;u+=y*640L;block=(short) (u/65536L);u-
=block*65536L;-FP-SEG(buf)=0xA000;-FP-OFF(buf)=u;-outp(0x3C4, 14);-outp(0x3C5,
block^2);for (i=0; i<n; i++,q+=mm) {if (action==-GPSET) -memcpy(buf, q, m);else
if(action==-GOR)for (j=0;j<m; j++) * (buf+j)|=(*(q+j));else if(action==-GAND)for (j=0;j<m;
j++) * (buf+j)&=(* (q+j));else if(action==-GXOR)for (j=0;j<m; j++) * (buf+j)^=(* (q+j));else
if(action==-GPRESET)for (j=0;j<m; j++) * (buf+j)=~(* (q+j));u+=640;if(u<65536L)
buf+=640;else {u-=65536L;-FP-SEG(buf)=0xA000;-FP-OFF(buf)=0;block++;-outp(0x3C4,
14);-outp(0x3C5, block^2);if (m>640-u) {if (action==-GPSET) -memcpy(buf,q+640-u,
(size-t)(m-640+u));else if(action==-GOR)for(j=0;j<m-640+u;j++) *(buf+j)|=(*(q+640-u+j));
else if(action==-GAND)for(j=0;j<m-640+u;j++) * (buf+j)&=(*(q+640-u+j));else if
(action==-GXOR)for(j=0;j<m-640+u;j++) * (buf+j)^=(*(q+640-u+j));else if(action==-
GPRESET)for(j=0;j<m-640+u;j++) * (buf+j)=~(* (q+640-u+j));}-FP-OFF(buf)=u;}}}