软件课程设计C语言实现BMP图像显示.doc

上传人:仙人指路1688 文档编号:2391835 上传时间:2023-02-17 格式:DOC 页数:29 大小:1.59MB
返回 下载 相关 举报
软件课程设计C语言实现BMP图像显示.doc_第1页
第1页 / 共29页
软件课程设计C语言实现BMP图像显示.doc_第2页
第2页 / 共29页
软件课程设计C语言实现BMP图像显示.doc_第3页
第3页 / 共29页
软件课程设计C语言实现BMP图像显示.doc_第4页
第4页 / 共29页
软件课程设计C语言实现BMP图像显示.doc_第5页
第5页 / 共29页
点击查看更多>>
资源描述

《软件课程设计C语言实现BMP图像显示.doc》由会员分享,可在线阅读,更多相关《软件课程设计C语言实现BMP图像显示.doc(29页珍藏版)》请在三一办公上搜索。

1、xx大学XX系课程设计报告(最终报告)( 2010 - 2011 年度第 2 学期)名 称: 软件课程设计 题 目:BMP图象分析与显示院 系: 班 级: 学 号: 学生姓名: 指导教师: 设计周数: 15 成 绩: 日期: 2011 年 5 月 31 日目 录1.设计任务12.基本思路23.方案设计23.1 主要算法说明23.2 程序框架设计94.程序的部分源代码分析及介绍145.调试过程中出现的问题及相应解决办法186.个人体会及建议267.参考文献27 1. 设计任务1.1利用C语言实现BMP格式图象文件的分析和显示。主要内容包括: a)基本任务:完成BMP格式图像的显示,要求在提供的画

2、布上循环的显示某一文件夹下面所有的BMP文件(支持所有BMP格式); b)拓展任务:实现图像的特效显示(淡入淡出,百页窗等等)。 1.2进度情况: A、我对BMP图像的了解BMP 文件是标准的Windows位图文件,有16色、256色、16位真彩色及24位 真彩色等格式。客观存在按文件头、图像控制信息、彩色表和位图点阵数据的格式来存储。文件头是定义图像文件的类型、长度等的数据结构:图像控制信息是定义图像颜色格式、图像大小、颜色数等的数据结构:彩色表是定义图像颜色的调色板的数组位图点阵,是定义图像数据的数组。未经压缩的BMP文件中,位图点阵信息是按扫描线从下至上(bottom to top)存储

3、的,即图像的第一个像素值在位图阵列的左下角,最后一个像素值在位图阵列的右上角。对16色位图,每个像素占4位,每个字节存放相邻的两个像素值,高4位存放的第1个像素值在扫描线的前面,低4位存放的第2个像素值在扫描线后面。对256色位图,1个字节存放1个像素值。对24位位图,颜色表为空,位图数据的每3个字节对应1个像素值,其中每个字节分别对应该像素值的P、R、G值。B、我对于BMP图像显示平台的理解1、通过enum来对各个按键(向上,向下,向左右等)作出定义2、定义结构体T_Message,用于接收和发出信号,来控制各个函数的进度。3、创建消息队列,用于控制各个程序的进度(即决定什么时候开始或者结束

4、它的进程)4、定义结构体变量T_MessageRecvMsg,用于接收从队列中发出的消息。5、利用函数DTOS_DRV_ReceiveMessage( Test_queueID, &RecvMsg),根据其中RecvMsg.param0的数值来决定是否进行这个进度。若RecvMsg.param0等于MSG_KeyRIGHT,则进行图像显示程序,获取图像名称,调用图像显示函数,对图像进行分析和显示;否则跳出循环。C、已能够正确显示32bit,24bit,1bit,4bit(未压缩),8bit(未压缩),4bit(压缩),8bit(压缩),16bit(1555模式,565模式,4444模式)的图像

5、。2. 基本思路通过查阅资料和自己的思考,猜想,我觉得要实现在画布上显示BMP图像,主要有以下几种方法 最初的想法是可以利用描点函数GFMSetPixels,逐个显示出BMP图像的点,最终构成一幅完整的图像。具体编码后,证实这是可行的。 查阅一些资料后,我了解到还可以利用粘贴函数GFMWriteRectangle。即将图像文件中的数据读取出来,用malloc动态分配内存,记录图像数据,然后将内存中数据拷贝到画布上的一个矩形框内,即实现了图像的显示。但是继续研究之后发现,这个方法涉及到将1,4,8,16,24bit图像数据修改为32bit的问题,比较复杂,所以最终还是采用了方案。3. 方案设计3

6、.1 主要算法说明:主要方法:将不同像素的图像分别用不同的函数实现,即分别定义show1bit,show4bit,show32bit等几个函数,再定义函数showbmp,按照需要显示的图像像素,决定调用相应的图像显示函数。这么做可以使结构比较清晰,增强代码的可读性。具体实现方法:定义信息头结构变量(其中变量包含BMP图像的文件头和信息头:文件标识“BM”,文件大小,保留位,数据偏移,信息头长度,宽度,高度,面数,像素的位数,压缩类型,位图数据大小,水平分辨率,垂直分辨率,颜色数,重要颜色)定义函数,读取文件头和信息头定义各个像素BMP图像的显示函数 32bit BMP图像的显示函数 定义文件指

7、针 用fopen打开图像文件 利用fseek函数将文件内部指针移到位图数据区,跳过信息头部分 用fread函数将颜色信息读取出来,存放在INT32U型的变量color中 调用画点函数GFMSetPixels,把color中的颜色信息显示在画布上 利用双重循环,依次逐行读取颜色信息,显示在画布上 显示结束,用fclose关闭文件 24bit BMP图像的显示函数 由于24bit图像和32bit图像一样,都没用调色板,所以实现过程相似,但有一点不同: 因为24bit的颜色信息占据3个字节,而32bit的颜色信息为4个字节,故利用fread函数读取颜色信息时,参数有所不同。 32bit:fread(

8、&color,4,1,fp); 24bit:fread(&color,3,1,fp): 8bit未压缩BMP图像的显示函数 由于8bit图像有调色板,故应当先定义数组来存放调色板的数据,然后在读取位图数据时,将数据对应的调色板颜色找出来,作为GFMSetPixels的颜色参数,描出一个点。 定义文件指针 定义存放调色板颜色数据的数组colorboard256,定义循环变量i,j和颜色变量color等用fopen打开图像文件 利用fseek函数将文件内部指针移到调色板数据区,跳过信息头部分 使用for循环,调用fread函数读出调色板数据放入数组colorboard256中:fread(&col

9、orboardi,4,1,fp); 注意用rewind(fp)重新定位指针到文件首部 重新使用fseek函数跳过信息头和调色板数据 fseek(fp,point-remove,0); 双重循环,依次读出位图数据。这里1字节的数据对应调色板中的一个颜色,所以用fread时数据长度的参数应当设为1。 for(i=0;ibmpheight;i+) for(j=0;jbmpwidth+1;j+) fread(&pcolor,1,1,fp);/读取一个位图数据 color=colorboardpcolor&0xff;/取读出的数据的一位,对应到调色板的一个颜色 if(jbmpwidth)GFMSetPi

10、xels(color,j,point-bmpheight-i,1); 显示结束,用fclose关闭文件 4bit未压缩BMP图像的显示函数 4bit图像也有调色板,也应当先定义数组来存放调色板的数据,然后在读取位图数据时,将数据对应的调色板颜色找出来,作为GFMSetPixels的颜色参数,描出一个点。但是和8bit图像略有不同的是,位图数据的4bit对应了调色板中的一个颜色数据,而不正好是1个字节,故应当对取出的位图数据做一些处理。 定义文件指针 定义存放调色板颜色数据的数组colorboard16,定义循环变量i,j和颜色变量color等用fopen打开图像文件 利用fseek函数将文件内

11、部指针移到调色板数据区,跳过信息头部分 使用for循环,调用fread函数读出调色板数据放入数组colorboard16中:fread(&colorboardi,4,1,fp); 注意用rewind(fp)重新定位指针到文件首部 重新使用fseek函数跳过信息头和调色板数据 fseek(fp,point-remove,0); 双重循环,依次读出位图数据。这里1/2字节(即4bit)的数据对应调色板中的一个颜色,所以应当把得到的位图数据拆成前后两部分,分别对应到调色板中的一种颜色。为了取得前面的4bit,使用二进制右移运算符,把不需要的4bit移出;为取得后面的4bit,使用按位与运算符&,把前

12、面的4bit置零。 for(i=0;ibmpheight;i+) for(j=0;jbmpwidth+1;j+) fread(&pcolor,1,1,fp);/读取一个位图数据 pcolor41=pcolor4&0x0f;/取出数据的前面4bit color=colorboardpcolor41;/对应到调色板的一个颜色 if(jbmpwidth)GFMSetPixels(color,2*j,point-bmpheight-i,1); pcolor42=pcolor&0x0f;/取出数据的后面4bit color=colorboardpcolor42;/对应到调色板的一个颜色 if(jbmpw

13、idth)GFMSetPixels(color,2*j+1,point-bmpheight-i,1); 显示结束,用fclose关闭文件 1bit BMP图像的显示函数 1bit图像也有调色板,也应当先定义数组来存放调色板的数据,然后在读取位图数据时,将数据对应的调色板颜色找出来,作为GFMSetPixels的颜色参数,描出一个点。但是它位图数据的1bit对应了调色板中的一个颜色数据,不正好是1个字节,故也应当对取出的位图数据做一些处理。 定义文件指针 定义存放调色板颜色数据的数组colorboard2,定义循环变量i,j和颜色变量color等用fopen打开图像文件 利用fseek函数将文件

14、内部指针移到调色板数据区,跳过信息头部分 使用for循环,调用fread函数读出调色板数据放入数组colorboard2中:fread(&colorboardi,4,1,fp); 注意用rewind(fp)重新定位指针到文件首部 重新使用fseek函数跳过信息头和调色板数据 fseek(fp,point-remove,0); 双重循环,依次读出位图数据。这里1/8字节(即1bit)的数据对应调色板中的一个颜色,所以应当按位将数据取出,分别对应调色板中的一个颜色数据。考虑再使用一重循环,每次把位图数据移动一位,取得每个位的数据。内层取位循环如下:for(k=0;k(7-k)&0x01;/取读出的

15、数据的一位color=colorboardpcolor1;/对应到调色板的一个颜色if(jbmpwidth)GFMSetPixels(color,8*j+k,point-bmpheight-i,1); 显示结束,用fclose关闭文件 vi 8bit 压缩BMP图像的显示函数 压缩算法:行程压缩编码的编码方式:由2个字节组成,第一个字节指定象素数目,第二个字节定义颜色索引,当第一个字节置零时,联合使用第二个字节中的值表示: 第二个字节的值为0:行的结束。 第二个字节的值为1:图象结束。 第二个字节的值为2:其后的两个字节表示下一个象素从当前开始的水平和垂直位置的偏移量。这个字节对中的第一个字节

16、设置为0,第二个字节包含有颜色索引数,其后续字节包含有颜色索引。故程序算法如下: 定义文件指针 定义存放调色板颜色数据的数组colorboard216,定义循环变量i,j,内部循环变量a,定义相同颜色数目和颜色索引颜色变量colornum, samecolor,行列偏移量iremove, jremove,对应到调色板颜色的数据pcolor和颜色变量color等(由于后面要对一个字节的数据进行判断,注意要把a,colornum,samecolor,iremove,jremove,pcolor设置成INT8U型,占一个字节并且无符号) 用fopen打开图像文件 利用fseek函数将文件内部指针移到

17、调色板数据区,跳过信息头部分 使用for循环,调用fread函数读出调色板数据放入数组colorboard216中:fread(&colorboardi,4,1,fp); 注意用rewind(fp)重新定位指针到文件首部 重新使用fseek函数跳过信息头和调色板数据 读取第一个相同颜色数的数据colornum,判断若不为0,转;若colornum为0,转 若colornum不为零,后一字节表示颜色索引,读取samecolor,将它对应到调色板:color=colorboardsamecolor; 利用for循环画出colornum个点。 若colornum为零,联合第二个字节判断。读取第二个字

18、节samecolor,若第二个字节为0,表示行结束,令行数加1,列变量置零;若第二个字节为1,表示RLE编码图像结束,用break退出循环;若第二个字节为2,其后的两个字节表示下一个象素从当前开始的水平和垂直位置的偏移量,用fread读取行列偏移量,把行列分别加上这两个数据;若第二个字节大于2,则第二个字节表示其后有效的颜色数据,利用for循环,设置条件为asamecolor,画出解压缩以后的点。 显示结束,用fclose关闭文件 vii 4bit 压缩BMP图像的显示函数 算法基本与8bit压缩图像一致,稍有不同如下:颜色索引数据samecolor(一个字节)分为两部分,高四位和低四位分别对

19、应两个调色板中的颜色。相同颜色数colornum的第一个对应高四位,第二个对应低四位,第三个对应高四位,以此循环。 viii 16bit BMP图像的显示函数 16bit图像有1555,4444,565三种模式。分别代表用于表示图像颜色数据的2字节(16bit)中RGB的值。1555中1代表混合参数,后面三个5分别表示RGB的值;4444中第一个4代表混合参数,后面三个4分别表示RGB的值; 565中5、6、5分别表示RGB的值。基本方法是利用位运算,分别得出不同模式下的RGB值,并对它们作出调整,使得RGB值都占一个字节,得出最终的颜色值。最后利用描点函数GFMSetPixels画出处理过的

20、颜色点。 定义文件指针 定义用于判断565和4444模式的变量a 用fopen打开图像文件 判断压缩类型bmprletype,若bmprletype值为0,转;若bmprletype值不为0,转 bmprletype=0,表示图像为1555模式。红色的掩码为(0111110000000000)2,即0x7c00;绿的掩码为(0000001111100000)2,即0x03e0;蓝的掩码为(0000000000011111)2,即0x001f。利用按位与运算得出RGB的值。R值原位于11位,经调整后,应当位于20位,故应该把按位与之后的结果左移9位。G、B值类似。三者相加得出最终颜色RGBcol

21、or。代码如下:RGBcolor=(color&0x7c00)9)+(color&0x03e0)6)+(color&0x001f)bmpheight-i,1); bmprletype不为零,利用a值进行判断。fread读取a的值fread(&a,4,1,fp);判断a值若为0xf800,则为565模式,转;若a值不为0xf800;为4444模式,转 a=0xf800,表示图像为为565模式。红色的掩码为(1111100000000000)2,即0xf800;绿的掩码为(0000011111100000)2,即0x07e0;蓝的掩码为(0000000000011111)2,即0x001f。利用按

22、位与运算得出RGB的值。移位方法与相似。三者相加得出最终颜色RGBcolor。代码如下:RGBcolor=(color&0xf800)8)+(color&0x07e0)5)+(color&0x001f)3);利用描点函数画出点 a!=0xf800,表示图像为为4444模式。红色的掩码为(0000111100000000)2,即0x0f00;绿的掩码为(0000000111110000)2,即0x00f0;蓝的掩码为(0000000000001111)2,即0x000f。利用按位与运算得出RGB的值。移位方法与相似。三者相加得出最终颜色RGBcolor。代码如下:RGBcolor=(color&

23、0x0f00)12)+(color&0x00f0)8)+(color&0x000f)2第二个字节表示其后有效的颜色数据相同颜色数目不为零,后一字节表示颜色索引读取颜色索引数据samecolor描点函数画出点 V 三种模式16bit图像(1555,444,565)显示流程开始打开图像文件,跳过信息头数据,fread读取调色板颜色信息,存入数组读取用于判断565和4444的数据a压缩类型bmprletype=?Y结束bmprletype=0a= 0xf800?利用位运算得出颜色数据的RGB值,再根据不同模式的算法进行调整得出颜色变量N1555模式bmprletype =3565模式描点函数画出点4

24、444模式4. 程序的部分源代码分析及介绍4.1 主要显示函数showbmpvoid showbmp(char *filename)/图像显示函数 FILE * fp; struct Filehead point; Readhead(filename,&point);/调用头信息读取函数获得图像头信息 if(fp=fopen(filename,rb)=NULL) printf(can not open); exit(1); switch(point.bmppix)/判断图像的颜色像素,决定使用哪个图像显示函数 case 1:/若像素为1,调用1bit图像显示函数 show1bit(filena

25、me,&point);break; /其余调用类似,这里省略关键是利用图像信息头中的bmppix(像素位数)来判断应当调用哪个图像显示函数4.2 32bit图像显示函数void show32bit(char*filename,struct Filehead* point)/显示32bit图像的函数 FILE*fp; INT32U color; INT32U i,j; if(fp=fopen(filename,rb)=NULL) printf(can not open the file!); exit(1); fseek(fp,point-remove,0);/跳过文件头信息头数据区 for(i

26、=0;ibmpheight;i+) for(j=0;jbmpwidth;j+) fread(&color,4,1,fp);/每次读取4个字节(即32bit)的数据 GFMSetPixels(color,j,point-bmpheight-i,1); fclose(fp);关键是用fseek跳过信息头,还有注意BMP图像读取时是从左下角开始的。 24bit图像显示函数与32bit基本一样,在第三部分已做过说明,这里不再赘述。4.3 8bit图像显示函数void show8bit(char*filename,struct Filehead* point) FILE*fp; INT32U color

27、,pcolor; INT32U i,j; INT32U colorboard256;/存放调色板数据的数组 if(fp=fopen(filename,rb)=NULL) printf(can not open the file!); exit(1); fseek(fp,0x36,0); for(i=0;iremove,0);/跳过信息头和调色板 for(i=0;ibmpheight;i+) for(j=0;jbmpwidth+1;j+) fread(&pcolor,1,1,fp);/读取一个位图数据 color=colorboardpcolor&0xff;/取读出的数据的一位,对应到调色板的一

28、个颜色 if(jbmpwidth)GFMSetPixels(color,j,point-bmpheight-i,1); 关键是定义数组来存放调色板的数据,然后在读取位图数据时对应到调色板中的颜色。4bit显示函数与8bit思路一致,但要注意有位运算。fread(&pcolor,1,1,fp);/读取一个位图数据pcolor41=pcolor4&0x0f;/取出数据的前面4bitcolor=colorboardpcolor41;/对应到调色板的一个颜色if(jbmpwidth) GFMSetPixels(color,2*j,point-bmpheight-i,1);pcolor42=pcolor

29、&0x0f;/取出数据的后面4bitcolor=colorboardpcolor42;/对应到调色板的一个颜色if(jbmpwidth) GFMSetPixels(color,2*j+1,point-bmpheight-i,1);1bit图像显示类似。4.4 8bit(压缩)图像显示函数void show8rlebit(char*filename,struct Filehead* point)/相同部分省略 INT8U colornum,samecolor, iremove,jremove, pcolor;/定义相同颜色数目,颜色索引,行列偏移量等/读取调色板数据与未压缩的一样,这里省略j=0

30、;for(i=0;ibmpheight;)fread(&colornum,1,1,fp);/读取第一个相同颜色数的数据if(colornum=0)/判断若为0,联合第二个字节判断fread(&samecolor,1,1,fp);/读取第二个字节if(samecolor=0)/第二个字节为0,表示行结束i+;j=0;else if(samecolor=1)/第二个字节为1,表示RLE编码图像结束break;else if(samecolor=2)/*第二个字节为2,其后的两个字节表示下一个象素从当前开始的水平和垂直位置的偏移量*/fread(&jremove,1,1,fp);fread(&ire

31、move,1,1,fp);i+=iremove;j+=jremove;else/若第二个字节大于2,则第二个字节表示其后有效的颜色数据 for(a=0;abmpheight-i,1);/画出解压缩以后的点j+;if(samecolor%2!=0) /若samecolor为奇数,再读取一个字节、fread(&pcolor,1,1,fp);else/相同颜色数目不为零,后一字节表示颜色索引fread(&samecolor,1,1,fp);/读取颜色索引数据 for(a=0;abmpheight-i,1);j+;fclose(fp);4bit压缩与8bit类似,不同点如下:for(a=0;asame

32、color;a+)if(a%2=0)/a为偶数,即第1,3,5,个颜色,对应高四位颜色 fread(&pcolor,1,1,fp); pcolor1=(pcolor&0xf0)bmpheight-i,1);/画出解压缩以后的点 j+; else/第2,4,6个颜色对应低四位 color2=colorboardpcolor2; GFMSetPixels(color2,j,point-bmpheight-i,1); j+; if(samecolor%4=1|samecolor%4=2)fread(&pcolor,1,1,fp);4.5 16bit(1555,4444,565模式)图像显示函数voi

33、d show16bit(char*filename,struct Filehead* point)/定义各种变量,打开文件等,与前面类似,这里省略 fseek(fp,point-remove,0); if(point-bmprletype=0)/1555类型 for(i=0;ibmpheight;i+) for(j=0;jbmpwidth+1);j+) fread(&color,2,1,fp);/读取2个字节的颜色数据RGBcolor=(color&0x7c00)9)+(color&0x03e0)6)+(color&0x001f)bmpheight-i,1); else if(point-bm

34、prletype=3) fread(&a,4,1,fp); fseek(fp,12,SEEK_CUR); if(a=0xf800)/565类型 /与1555类似,不同点在于RGB掩码以及处理方式: RGBcolor=(color&0xf800)8)+(color&0x07e0)5)+(color&0x001f)3); else if(a!=0xf800)/4444类型 /与1555类似,不同点在于RGB掩码以及处理方式:、RGBcolor=(color&0x0f00)12)+(color&0x00f0)8)+(color&0x000f)remove,0); 或者fseek(fp,54,0);这

35、样就解决了问题 问题二 问题:编写的32bit图像显示函数调试运行后出现如下结果(下图) 问题原因分析:由显示可知,图像的上下颠倒,可能是使用描点函数GFMSetPixels时,参数y弄错了。而由本文1.2可知,位图点阵信息是按扫描线从下至上(bottom to top)存储的,即图像的第一个像素值在位图阵列的左下角,最后一个像素值在位图阵列的右上角。 解决方法:原来的绘图函数为 GFMSetPixels(color,j, i,1); 将它改为GFMSetPixels(color,j,point-bmpheight-i,1);这样就解决了问题。 问题三问题:编写的24bit图像显示函数调试运行

36、后出现如下结果(下图)问题原因分析:请教老师之后得知,在读取图像时,所有图像的像素宽度都应当是4的倍数,而这幅24bit图像的大小为711*533,而宽度711*3=2133不能被4整除解决方法:可以利用如下算法,把任意一张图片的宽度调整为4的倍数:(width*3) 1行有效的字节数;(width*3)%4 被4除余数是多少4-(width*3)%4 需要补充的字节数(4-(width*3)%4)%4 width*3如果是4的倍数,那么上面的计算结果等于4,在对4取余,得到的就是每一行填充的字节数。patch = (4-(width*3)%4)%4;for(i=0;iheight;i+) for(j=0;jwidth;j+) fread(&color, 3, 1, fp); GFMSetPixels(color, j, i, 1); fseek(fp, patch, SEEK_CUR);对于16bit的图片,patch=(4-(width*2)%4)%4;对于8bit的图片,patch=(4-(width)%4)%4;对于4bit的图片,patch=(8-(width*2)%8)%8;对于1bit的图片,patch=(32-(width*32)%32)%32;

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 建筑/施工/环境 > 项目建议


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号