图像漫游论文

时间:2022-09-17 05:30:00

图像漫游论文

VGA是微机显示的廉价适配器,因而在其上实现图形图像处理的成本较低。在目前国内流行的C语言中,均提供了基本的作图函数,如BorlandcC++、TurboC和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个画面的漫游,其方法相同。

三、基本功能函数

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

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

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

scroll_x——X轴向漫游函数。

scroll_y——Y轴向漫游函数。

1.常数定义及函数说明

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

#defineXP116/*窗口左上角坐标*/

#defineYP132

#defineXP2591/*窗口右下角坐标*/

#defineYP2415

#defineLEFT0x4b

#defineRIGHT0x4b

#defineUP0x48

#defineDOWN0x50

#defineINDEXREG10x3CE/*VGA图形控制器索引寄存器*/

#defineVALREG10x3CF/*VGA图形控制器数据寄存器*/

#defineINDEXREG20x3C4/*VGA定序器索引寄存器*/

#defineVALREG20x3C5/*VGA定序器数据寄存器*/

·#defineVGABASE0xA0000000L/*VGA640*48016色模式起始地址*/

voidsavewin(char*,int,int,int,int,int,int);

voidLoadwin(char*,int,int,int,int,int,int,int);

voidscroll_x(int,int,int,int,int);

voidscroll_y(int,int,int,int,int)

2、功能函数

/*文件名:function.cpp*/

#include<stdio.h

#include<stdlib.h>

#include<conio.h>

#include"scroll.h"

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

fname存放漫游图文件;

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

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

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

nxynxy*nxy拼图*/

voidsavewin(char*fname,intxleft,intytop,intxright,intybuttom,intnu

mber,intnxy)

{

FILE*fp;

inti,width,height;

registerj,k;

Longtemp,offset,offset1;

charfar*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<4;i++){

outportb(INDEXREG1,4);

outportb(VALREG1,i);

base=(charfar)*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<height;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拼图*/

voidLoadwin(char*fname,intxo,inty0,intxleft,intytop,intxright,int

ybuttom,intnxy)

{

FILE*fp;

registerintj,i,n=8,width,height;

charfar*base,*vbase;

registerlongoffset;

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=(charfar*)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<height;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>向下漫游(以象素为单位)*/

voidscroll-y(intxleft,intytop,intxright,intybuttom,intdy)

{

intwidth,height,temp;

registeri,j;

charfar*base,far*tbase;

longoffset,toffset;

outportb(INDEXERG1,5);

outportb(VALREG1,1);

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

height=ybuttom-ytop+1;

if(dy<0){

base=(charfar*)VGABASE+(long)(ytop*80)+(long)(xleft/8);

tbase=base;

toffset=(long)dy*80L;

temp=height+dy;/*whenmovetoupdy<0*/

for(i=0;i<temp;i++){

for(j=0;j<width;j++){

*base=*(base-toffset);

base++;

}

tbase=tbase+80L;

base=tbase;

}

}

else

{

base=(charfar*)VGABASE+(long)(ybuttom*80)+(long)(xleft/8);

tbase=base;

toffset=(long)dy*80L;

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

for(i=0;i<temp;i++){

for(j=0;j<width;j++){

*base=*(base-toffset);

base++;

}

tbase=tbase-80L;

base=tbase;

}

}

outportb(INDEXREG1,0);

}

/*X-方向漫游函数

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

dx<0向左漫游(以8个象素为单位);

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

voidscroll-x(intxleft,intytop,intxright,intybuttom,intdx)

{

intwidth,height,temp;

registeri,j;

charfar*base,far*tbase;

longoffset;

outportb(INDEXREG1,5);

outportb(VALREG1,1);

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

height=ybuttom-ytop+1;

if(dx<0){

base=(charfar*)VGABASE+(long)(ytop*80)+(long)(xleft/8);

tbase=base;

temp=width+dx;/*whenmovetoleftdx<0*/

for(i=0;i<height;i++){

for(j=0;j<temp;j++){

*base=*(base-dx);

base++;

}

tbase=tbase+80L;

base=tbase;

}

}

else

{

base=(charfar*)VGABASE+(long)(ytop*80)+(long)((xright-7)/8;

tbase=base;

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

for(i=0;i<height;i++){

for(j=0;j<temp;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<stdio.h>

#include<stdlib.h>

#include<conio.h>

#include<dos.h>

#include<graphic.h>

#include"scroll.h"

voikdmain(void)

{

FILE*fp;

charch;

charfar*ptr;

intX1,Y1,X2,Y1;

intgdriver=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<stdio.h>

#include<stdlib.h>

#include<conio.h>

#include<dos.h>

#include<graphic.h>

#include"scroll.h"

intmdx=0,mdy=0;

voidmain(void)

{

FILE*fp;

charch;

charfar*ptr;

intgdriver=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){

caseDOWN:/*向下滚动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;

caseUP:/*向上滚动64行*/

if(mdy<(YP2-YP1+1)/64){

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;

caseLEFT:

if(mdy<(XP2-XP1+1)/64){

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;

caseRIGHT:

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();