欢迎您访问科普小知识本站旨在为大家提供日常生活中常见的科普小知识,以及科普文章!
您现在的位置是: 首页

VGA16色模式下的图像漫游

科普小知识 2023-11-14 12:01:39
...

vga是微机显示的廉价适配器,因而在其上实现图形图像处理的成本较低。在目前国内流行的c语言中,均提供了基本的作图函数,如borlandc c++、turbo c和microsoftc。但还缺少一个最基本的图形图像处理功能-屏幕漫游功能。本文将讨论在vga16色模式下实现屏幕图像漫游的方法,并给出c语言的程序供读者参考。

一、基本构思

为了实现漫游的功能,首先将想像中的大幅图像分成n×n块(每块应小于屏幕的分辨率)相同大小的区域,然后逐次显示在屏幕上并存放到一个文件中。这样就完成了漫游图的制作。可以设想,文件提供了一个无限分辨率的虚拟屏幕,存储着大幅图像数据。

在调用漫游图时,将存放在文件中的图像数据的一部分显示在屏幕上,当用键盘或鼠标控制图像漫游时,程序首先将屏幕上的图像移动一定的距离,这一过程实质是硬件漫游。当屏幕图像移动后,留出的空白位置则从文件中调出数据显示到屏幕上,这一步实质为软件漫游。

二、存图文件的数据结构

假设在文件zoom.scr中存储了2×2个vga(640×480×16色模式)窗口画面,窗口的范围如图1所示。其左上角和右下角的坐标分别为(xp1,yp1)、(xp2,yp2),将来就在这一窗口范围内进行漫游。

@@t5s11100.gif;图1@@

假设存图时每个窗口大小一样,高度为d,宽度为w。存图时漫游窗口的宽度与起始坐标均为8的整数倍,这样便于处理。四个窗口的排号顺序如图2所示:

@@t5s11101.gif;图2@@

在此是实现2×2画面的漫游功能,用户可根据需要实现n×n个画面的漫游,其方法相同。www.11665.CoM

三、基本功能函数

实现漫游功能主要由以下几个函数实现

savewin——存图函数,将屏幕窗口函数存入文件。

loadwin——调图函数,由文件将图像数据调入屏幕。

scroll_x——x轴向漫游函数。

scroll_y——y轴向漫游函数。

1.常数定义及函数说明

/*文件名:scroll.h*+/

# define xp1 16 /* 窗口左上角坐标 */

# define yp1 32

# define xp2 591 /* 窗口右下角坐标*/

# define yp2 415

# define left 0x4b

# define right 0x4b

# define up 0x48

# define down 0x50

# define indexreg1 0x3ce /* vga图形控制器索引寄存器 */

# define valreg1 0x3cf /* vga图形控制器数据寄存器 */

# define indexreg2 0x3c4 /* vga定序器索引寄存器*/

# define valreg2 0x3c5 /* vga定序器数据寄存器 */

·# define vgabase 0xa0000000l /* vga 640*480 16色模式起始地址 */

void savewin (char *,int,int,int,int,int,int);

void loadwin (char *,int,int,int,int,int,int,int);

void scroll_x (int,int,int,int,int);

void scroll_y (int,int,int,int,int)

2、功能函数

/* 文件名:function.cpp*/

# include

# include

# include

# include "scroll.h"

/*制作漫游图时存入窗口函数,

fname存放漫游图文件;

(xleft,ytop)在屏幕上窗口左上角坐标;

(xright,ybuttom)在屏幕上窗口左上角坐标;

number图号(0-nxy×nxy-1)

nxy nxy*nxy拼图*/

void savewin(char *fname,int xleft,int ytop,int xright,int ybuttom,int nu

mber,int nxy)

{

file *fp;

int i,width,height;

register j,k;

long temp,offset,offset1;

char far *base;

width=(xright-xleft+1)/8;

height=ybuttom-ytop+1;

fp=fopen(fname,"rb+");

offset=(long)(number-number%nxy)*(long)width*(long)height;

offset1=offset;

for(i=0;i

outportb(indexreg1,4);

outportb(valreg1,i);

base=(char far)*vgabase+(long)(ytop*80)+(long)(xleft/8);

offset=(long)(i*nxy*nxy)*(long)width*(long)height+(long)(number%nxy)*(l

ong)width+offset1;

for(j=0;j

fseek(fp,offset,seek_set);

fwrite(base,1,width,fp);

offset=offset+(long)(nxy*width);

base=base+80l;

}

}

fclose(fp);

outportb(indexreg1,0);

}

/* 向屏幕装入漫游图窗口函数,

(x0,y0)装入屏幕起始坐标;

fname存放漫游图文件名;

(xleft,ytop)在fname中虚拟窗口左上角坐标;

(xright,ybuttom)在fname中虚拟窗口右下角坐标;

nxynxy*nxy拼图*/

void loadwin(char *fname,int xo,int y0,int xleft,int ytop,int xright,int

ybuttom,int nxy)

{

file *fp;

register int j,i,n=8,width, height;

char far *base,*vbase;

register long offset;

fp=fopen(fname,"rb");

width=(xright-xleft+1)/8;

height=ybuttom-ytop+1;

for(i=3;i>0;i--) {

outportb(indexreg1,5);

outportb(valreg1,0);

outportb(indexreg2,2);

outportb(valreg2,n);

base=(char far*)vgabase+(long)y0×80l+(long)(x0/8);

offset=(long)(i*nxy*nxy)*(long)(yp2-yp1+1)*(long)((xp2-xp1+1)/8)+(long)(x

left/8)+(long)(ytop*nxy)*(long)((xp2-xp1+1)/8);

for(j=0;j

fseek(fp,offset,seek_set);

fread(base,1,width,fp);

offset=offset+(long)nxy*(long)((xp2-xp1+1)/8);

base=base+80l;

}

n=n/2;

}

fclose(fp);

outportb(valreg2,oxff);

outportb(indexreg2,oxf);

outportb(indexreg1,0);

}

/* y-方向漫游函数

(xleft,ytop,xright,ybuttom)定义漫游窗口;

dy

dy>向下漫游(以象素为单位)*/

void scroll-y(int xleft,int ytop,int xright,int ybuttom,int dy)

{

int width,height,temp;

register i,j;

char far *base,far *tbase;

long offset,toffset;

outportb(indexerg1,5);

outportb(valreg1,1);

width=(xright-xleft+1)/8;

height=ybuttom-ytop+1;

if(dy

base=(char far *)vgabase+(long)(ytop*80)+(long)(xleft/8);

tbase=base;

toffset=(long)dy*80l;

temp=height+dy; /* when move to up dy

for(i=0;i

for(j=0;j

*base=*(base-toffset);

base++;

}

tbase=tbase+80l;

base=tbase;

}

}

else

{

base=(char far *)vgabase+(long)(ybuttom*80)+(long)(xleft/8);

tbase=base;

toffset=(long)dy*80l;

temp=height-dy; /*dy>0 */

for(i=0;i

for(j=0;j

*base=*(base-toffset);

base++;

}

tbase=tbase-80l;

base=tbase;

}

}

outportb(indexreg1,0);

}

/* x-方向漫游函数

(xleft,ytop, xright,ybuttom)定义漫游窗口;

dx

dx>0 向右漫游(以8个象素为单位) */

void scroll-x(int xleft,int ytop,int xright,int ybuttom,int dx)

{

int width,height,temp;

register i,j;

char far *base,far *tbase;

long offset;

outportb(indexreg1,5);

outportb(valreg1,1);

width=(xright-xleft+1)/8;

height=ybuttom-ytop+1;

if(dx

base=(char far *)vgabase+(long)(ytop*80)+(long)(xleft/8);

tbase=base;

temp=width+dx; /* when move to left dx

for(i=0;i

for(j=0;j

*base=*(base-dx);

base++;

}

tbase=tbase+80l;

base=tbase;

}

}

else

{

base=(char far *)vgabase+(long)(ytop*80)+(long)((xright-7)/8;

tbase=base;

temp=width-dx; /* dx>0 */

for(i=0;i

for(j=0;j

*base=*(base-dx);

base--;

}

tbase=tbase+80l;

base=tbase;

}

}

outportb(indexreg1,0);

}

四、示例

示例exm1.cpp中,首先在虚拟的大幅漫游图上画一个贯穿整个漫游图的“×”,然后按2×2

图幅存入zoom.scr文件。在示例exm2.cpp中,通过方向键控制图像漫游。

[程序1]exm1.cpp

# include

# include

# include

# include

# include

# include"scroll.h"

voikd main(void)

{

file *fp;

char ch;

char far *ptr;

int x1,y1,x2,y1;

int gdriver=detect,gmode;

initgraph(&gdriver,*gmode,"");

setcolor(red);

line(xp1,yp1,xp2,yp2);

savewin("zoom.scr",xp1,yp1,xp2,yp2,1,2);

cleardevice();

line(xp1,yp1,xp2,yp2);

savewin("zoom.scr",xp1,yp1,xp2,yp2,4,2);

cleardevice();

line(xp2,yp1,xp1,yp2);

savewin("zoom.scr",xp1,yp1,xp2,yp2,2,2);

cleardevice();

line(xp2,yp1,xp1,yp2);

savewin("zoom.scr",xp1,yp1,xp2,yp2,3,2);

closegraph();

}

[程序2]exm2.cpp

# include

# include

# include

# include

# include

# include"scroll.h"

int mdx=0,mdy=0;

void main(void)

{

file *fp;

char ch;

char far *ptr;

int gdriver=detect,gmode;

initgraph(&gdriver,*gmode,"");

/* 将存贮在zoom.scr中对应的左上角的部分图像装入屏幕窗口 */

loadwin("zoom.scr",xp1,yp1,0,0,xp2-xp1,yp2-yp1,2);

/* 以下循环利用方向键控制图像漫游,“q”键退出*/

do {

ch=getch();

if(ch==0) ch=getch();

if(ch=="q"||ch=="q") break;

switch(ch){

case down: /* 向下滚动64行*/

if (mdy>0) {

mdy--;

scroll-y(xp1,yp1,xp2,yp2,64);

loadwin("zoom.scr",xp1,yp1,64*mdx,64*mdy,xp2-xp1+64*mdx,64*(mdy+1)-

1,2)

}

break;

case up: /* 向上滚动64行 */

if (mdy

scroll-y(xp1,yp1,xp2,yp2,-64);

loadwin("zoom.scr",xp1,yp2-63,64*mdx,yp2-yp1+1+64*mdy,xp2-xp1+64*mdx

,yp2-yp1+64*(mdy+1),2);

mdy++;

}

break;

case left:

if(mdy

scroll-x(xp1,pp1,xp2,yp2,-8);

loadwin("zoom.scr",xp2-63,yp1,xp2-xp1+1+64*mdx,64*mdy,xp2-xp1+64*(m

dx+1),yp2-yp1+64*mdy,2);

mdx++;

}

break;

case right:

if (mdx>0) {

mdx--;

scroll-x(xp1,yp1,xp2,yp2,8);

loadwin("zoom.scr",xp1,yp1,64*mdx,64*mdy,64*(mdx+1)-1,yp2-yp1+64*md

y,2);

}

break;

} while(ch!='q');

closegraph();

}