第四讲BMP文件的艺术再现.docx
- 文档编号:29733591
- 上传时间:2023-07-26
- 格式:DOCX
- 页数:22
- 大小:846.93KB
第四讲BMP文件的艺术再现.docx
《第四讲BMP文件的艺术再现.docx》由会员分享,可在线阅读,更多相关《第四讲BMP文件的艺术再现.docx(22页珍藏版)》请在冰豆网上搜索。
第四讲BMP文件的艺术再现
鹏程C语言教学网站版权所有
C语言高级程序设计讲座
第四讲BMP文件的艺术再现
鹏程C语言教学网站庆祝建站一周年特别企划
技术支持:
http:
//202.112.86.129
现在很多软件都有一个好看的封面,封面就像一个软件的门面,从第一感官刺激别人的视线。
下面我们先来看一下下面几个软件的封面:
图一金山WPSOffice办公组合
图二AdobePhotoshop6.0
图三沈阳电力机械总厂财务部成本管理系统II
在C语言中,我们也可以给软件加上一个好的封面,这会给你的程序添色不少。
学习目标
·BMP文件的存储格式
·DOS方式下调用BMP图像的手段
·艺术再现BMP图像
BMP文件的存储格式
BMP文件是标准的Windows位图文件,有16色、256色、16位真彩色及24位真彩色等格式。
客观存在按文件头、图像控制信息、彩色表和位图点阵数据的格式来存储。
文件头是定义图像文件的类型、长度等的数据结构:
图像控制信息是定义图像颜色格式、图像大小、颜色数等的数据结构:
彩色表是定义图像颜色的调色板的数组位图点阵,是定义图像数据的数组。
未经压缩的BMP文件中,位图点阵信息是按扫描线从下至上(bottomtotop)存储的,即图像的第一个像素值在位图阵列的左下角,最后一个像素值在位图阵列的右上角。
对16色位图,每个像素占4位,每个字节存放相邻的两个像素值,高4位存放的第1个像素值在扫描线的前面,低4位存放的第2个像素值在扫描线后面。
对256色位图,1个字节存放1个像素值。
对24位位图,颜色表为空,位图数据的每3个字节对应1个像素值,其中每个字节分别对应该像素值的P、R、G值。
DOS方式下调用BMP图像的手段
再现一副非压缩静止位图,主要需下面三个步骤:
·设置显示模式;
·打开位图文件,读取图像控制信息,设置调色板;
·读取位图数据度进行显示。
若图像数据是以堵塞压缩的,那么先解压,然后再按上面的步骤进行。
设置显示模式
随着计算机硬件的不断发展,尤其是显示卡和显示椿性能的提高,显示效果越来越好。
图像显示效果主要体现在图像分辨率和颜色两个方面,分辨率反映图像的清晰和谐,而颜色则反映了图像与物体本来颜色的逼真程度。
虽然,对一个图形图像界面的评价涉及人的审美观,心理因素等主观原因,但也有客观的标准。
高分辨率和真彩色是人分辨率追求的最高目标。
现在,性能好的显示卡和显示器(如SUPERVGA)能支持高达1024X768的分辨率,可以表示的颜色数目可达2:
4种。
对于DOS用户而言,常用的是640X480分辨率/16色、320X200分辨率/256色和640X480分辨率/256色等几种模式,它们分别是VGA/TVGA中的12h、13h和5dh模式。
可通过直接调用DOS的10h中断来设置:
相应的函数定义如下:
intSet640_480(void)
{
asmmovax,4fO2h
asmmovbx,OlOlh
asmintlob
if((_AL==0x4f)&&(_AH==0))
{
return(0);
}
return
(1)
}
调色板的设置
在DOS环境下显示Windows位图时,由于DOS调色板与Windows调色板不同,因此需自行设置Windows调色板,这样,图像才能不失真地显示所需的颜色并与原图像颜色相匹配。
具体操作是从图像文件中读出彩色表数值,调用函数int86x写入Windows调色板控制区域。
相应的函数定义如下:
voidset_windows_palette16(unsignedcharbmp_top[])
/*设置调色板*/
{inti;
unsignedcharchg[]={0,1,2,3,4,5,20,7,56,57,58,59,60,61,62,63};
intf[16]={0,4,2,6,1,5,3,8,7,12,10,14,9,13,11,15};
for(i=O;i<-I5;i++)
(outportb(Ox3c8,chg[f[i]]);
outportb(Ox3c9,bmptop[54+i*4+2]/4);
outportb(Ox3c9,bmp_top[5,~+i*4+1]/4);
outportb(Ox3c9,bmptop[54+i*4~-0]/4);}
}
intbmp_out(intx,inty,char*bmp_name)
/*打开文件名为*bmp_name的文件,在(x,y)位置输出图像*/
{
inti,j,k,l=0,c1,c2,x1,y1;
unsignedcharh,bmp_top[128],w,b=0x80,x0;
charfar*ptr=-(charfar*)0xa0000000;
charfar*p;
intfi16]={0,4,2,6,1,5,3,8,7,12,10,14,9,13,11,15};
FILE*fp;
if((fp=fopen(bmpname,"rb"))==NULL)return
(1)
fread(bmp_top,118,1,fp);
set_windows_palette16(bmp_top);
xl=bmp_top[18]+bmp_top[19]*256;
y1=bmp_top[22]+bmp_top[23]*256;
c1=(8-x1%8)/2;c2=x1%8;
x0=b>>(x%8);
ptr+=(rdS+80*(y+yl));
outportb(Ox3ce,5);outportb(Ox3cf,2);
for(i=O;i { j=0;b=x0; for(l=0;l { h=getc(fp); outportb(Ox3ce,8);outportb(Ox3cf,b);b>>=1; p=ptr-i*80+j; w=*p; *p=f[h>>4]; if(! b){b=OxSO;j++;} if(x1%2&&l==x1-1)break; outportb(Ox3ce,8);outportb(Ox3cf,b);b>>=1 p=ptr-i*80+j; w=*p; *p=f[h&OxOf]; if(! b){b=Ox80;j++;} } if(c2)for(k--O;k } outportb(Ox3ce,8);outportb(Ox3cf,255); outportb(Ox3ce,5);outportb(Ox3cf,O); fclose(fp); return(O);} 图像再现 下面我们来看一个例子,调出一幅BMP图像。 #include"conio.h" #include"stdio.h" #include"dos.h" #include"stdlib.h" #definelengthlimit640 #definehighlimit480 intSet640_480(void) { asmmovax,4f02h asmmovbx,0101h asmint10h if((_AL==0x4f)&&(_AH==0)) { return(0); } return (1); } voidSet_Page(intpage) { asmmovax,4f05h asmmovbx,0 asmmovdx,page asmint10h } voidmyputpixel(introw,intcol,unsignedcharcolor) /*(row,col)画点的坐标,color画点颜色*/ { unsignedlongdantance; unsignedy; staticinttotalpage=0; intpage; dantance=1l*col*lengthlimit+row; y=(unsigned)(dantance&0X0000ffffl); page=(int)(1.0*dantance/65536); if(totalpage! =page){totalpage=page;Set_Page(page);} asm{ movax,0a000h moves,ax movsi,y moval,color moves: [si],al } } voidbmpout(char*bmpstr) /*打开文件名为*bmpstr的BMP文件,输出图象*/ { FILE*bmpfp; structbmp{ intbftype; longbfsize; longbfr; longbfoff; longbisize; longbiwidth; longbiheight; }bmpp; structDAC{ charblue; chargreen; charred; }; structDACdacp[256]; charpp; intcolorcount,x,y,i,j,x0=0,y0=470,k,bibit,svg; charresev,buf1; void*buf; Set640_480(); if((bmpfp=fopen(bmpstr,"rb"))==NULL) { printf("can'topenfile"); return; } fread(&bmpp,sizeof(bmpp),1,bmpfp); fseek(bmpfp,28l,SEEK_SET); fread(&bibit,2,1,bmpfp); fseek(bmpfp,46l,SEEK_SET); fread(&colorcount,sizeof(colorcount),1,bmpfp); if(colorcount==0){colorcount=256;} fseek(bmpfp,54l,SEEK_SET); for(i=0;i { fread(&dacp[i],3,1,bmpfp); fread(&resev,1,1,bmpfp); } for(i=0;i { pp=dacp[i].red>>2; dacp[i].red=dacp[i].blue>>2; dacp[i].blue=pp; dacp[i].green=(dacp[i].green>>2); } asmpushes _ES=FP_SEG(dacp); _DX=FP_OFF(dacp); asmmovbx,0 asmmovcx,colorcount asmmovah,10h asmmoval,12h asmint10h asmpopes fseek(bmpfp,bmpp.bfoff,SEEK_SET); buf=malloc(bmpp.biwidth); for(i=0;i { y=y0-i; fread(buf,bmpp.biwidth,1,bmpfp); for(j=x0;j myputpixel(j,y,*((unsignedchar*)buf+j)); } free(buf); getch(); fclose(bmpfp); delay(500); return; } voidmain() { bmpout("*.bmp");/*打开某一BMP文件并输出图象*/ } 下例采用了随即函数产生点的颜色,输出到屏幕缓冲区,得到迷幻的图像。 #include #include #include longAddr[768]; intMode; Set_Mode(intmode) { unionREGSr; r.h.ah=0; r.h.al=mode; int86(0x10,&r,&r); } Set_Graphics_Mode(unsignedx,unsignedy) { longi; if((x<321)&&(y<201)){ Set_Mode(0x13); Mode=0x13; for(i=0;i<200;i++)Addr[i]=320*i; } elseif((x<641)&&(y<401)){ Set_Mode(0x5c); Mode=0x5c; for(i=0;i<400;i++)Addr[i]=640*i; } elseif((x<641)&&(y<481)){ Set_Mode(0x5d); Mode=0x5d; for(i=0;i<480;i++)Addr[i]=640*i; } elseif((x<641)&&(y<481)){ Set_Mode(0x5d); Mode=0x5d; for(i=0;i<480;i++)Addr[i]=640*i; } elseif((x<801)&&(y<601)){ Set_Mode(0x5e); Mode=0x5e; for(i=0;i<600;i++)Addr[i]=800*i; } elseif((x<1025)&&(y<769)){ Set_Mode(0x62); Mode=0x62; for(i=0;i<768;i++)Addr[i]=1024*i; } else{ Set_Mode(3); printf("Notsupportthismode.\n"); getch(); } } set_pattern() { inti; unsignedcharpat[256][3]; structSREGSinreg; unionREGSreg; pat[0][0]=0;pat[0][1]=0;pat[0][2]=0; for(i=1;i<=255;i++){ pat[i][0]=(unsignedchar)((float)(abs(i-127)*63)/127.0+0.5); pat[i][1]=(unsignedchar)((float)(abs(i-127)*63)/127.0+0.5); pat[i][2]=63; } reg.x.ax=0x1012; reg.x.bx=0; reg.x.cx=256; reg.x.dx=FP_OFF(pat); inreg.es=FP_SEG(pat); int86x(0x10,®,®,&inreg); } plot(intx,inty,unsignedcharcolor) { longoffset; charPage; unsignedcharfar*address; switch(Mode){ case0x13: offset=Addr[y]+x; address=(unsignedcharfar*)(0xa0000000L+offset); *address=color; break; case0x5c: case0x5d: case0x5e: offset=Addr[y]+x; Page=(offset>>16); outportb(0x3c4,0xe); outportb(0x3c5,Page^0x02); offset=offset&65535; address=(unsignedcharfar*)(0xa0000000L+offset); *address=color; break; case0x62: offset=Addr[y]+x; Page=y>>6; outportb(0x3c4,0xe); outportb(0x3c5,Page^0x02); offset=offset&65535; address=(unsignedcharfar*)(0xa0000000L+offset); *address=color; break; default: break; } } get_pixel(intx,inty) { longoffset; charPage; unsignedcharfar*address; unsignedcharcolor; switch(Mode){ case0x13: offset=Addr[y]+x; address=(unsignedcharfar*)(0xa0000000+offset); color=*address; break; case0x5c: case0x5d: case0x5e: offset=Addr[y]+x; Page=(offset>>16); outportb(0x3c4,0xe); outportb(0x3c5,Page^0x02); offset=offset&65535; address=(unsignedcharfar*)(0xa0000000L+offset); color=*address; break; case0x62: offset=Addr[y]+x; Page=y>>6; outportb(0x3c4,0xe); outportb(0x3c5,Page^0x02); offset=offset&65535; address=(unsignedcharfar*)(0xa0000000L+offset); color=*address; break; default: break; } return(color); } randint(unsignedintrange) { floatsigma=423.1966; staticdoubleOldRand=0.4231967; doubletemp; temp=sigma*OldRand; OldRand=temp-(int)temp; return(int)(OldRand*(float)range); } voidNew_Col(intxa,intya,intx,inty,intxb,intyb) { unsignedintcolor; color=abs(xa-xb)+abs(ya-yb); color=randint(color<<1)-color; color=color+(get_pixel(xa,ya)+get_pixel(xb,yb)+1)>>1; if(color<1)color=1; elseif(color>255)color=255; if((get_pixel(x,y)==0))plot(x,y,color); } voidSub_Divide(intx1,inty1,intx2,inty2) { intx,y; unsignedcharcolor; if(! ((x2-x1<2)&&(y2-y1<2))){ x=(x1+x2)>>1; y=(y1+y2)>>1; New_Col(x1,y1,x,y1,x2,y1); New_Col(x2,y1,x2,y,x2,y2); New_Col(x1,y2,x,y2,x2,y2); New_Col(x1,y1,x1,y,x1,y2); color=(get_pixel(x1,y1)+get_pixel(x2,y1)+get_pixel(x2,y2)+get_pixel(x1,y2)+2)>>2; plot(x,y,color); Sub_Divide(x1,y1,x,y); Sub_Divide(x,y1,x2,y); Sub_Divide(x,y,x2,y2); Sub_Divide(x1,y,x,y2); } } main() { intx,y; x=320;y=200; Set_Graphics_Mode(x,y); set_pattern(); plot(0,0,randint(254)+1); plot(x-1,0,randint(254)+1); plot(x-1,y-1,randint(254)+1); plot(0,y-1,randint(254)+1); Sub_Divide(0,0,x-1,y-1); getch(); Set_Mode(0x03); } 艺术再现BMP图像 大家都用过PowerPoint吧,所谓艺术再现就是指把图像通过一些特效展现出来。 这可以通过C语言来编写,感兴趣的同学不妨通过上面学到的知识来自己动手编写一下。 文章转载 下文是原版主wujin的一篇文章,我们不妨拿来看看。 显示256色BMP位图 学习该文章应具备的预备知识: (1)VGA显示系统 (2)BMP图像文件格式 (3)256色模式写屏 以上文章在TC256专题站(http: \\或http: \\)均有介绍。 学习该文章的补充知识: 1.VGA的DAC色彩寄存器知识 前面我已经讲过,16色和256色模式显示时,需要一张颜色表,以将显存的数据“翻译”为屏幕上的点信息。 该颜色表在显卡芯片中其实对应一组寄存器,该寄存器就是DAC色彩寄存器,在非真彩色的屏幕模式下,修改了DAC寄存器的值,就相当于修改了显存中某种色号对应的色彩信息。 在VGA及其兼容卡中,一共有256个该寄存器构成了一片存储单元,该单元就是显示器的DAC色表。 在256色BMP位图中,也有这样一张色表,记录了该图片不同色彩信息对应的RGB值,该色表位于BMP文件54字节的位置处,按照: B、G、R、alpha的顺序排列的,但该RGB信息与DAC色彩寄存器的信息不同,DAC寄存器需要的颜色以6位表示,即最大值为0x3F,而该BMP中的色表以8位表示,最大值为0xFF。 因此,要将BMP位图的颜色信息换
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第四讲 BMP文件的艺术再现 第四 BMP 文件 艺术 再现
![提示](https://static.bdocx.com/images/bang_tan.gif)