xx大学XX
课程设计报告(最终报告)
( 2010 -- 2011 年度第 2 学期)
名    称:   软件课程设计 
  题    目:BMP图象分析与显示
院    系: 
班    级:
学    号:
学生姓名:
指导教师:
设计周数:      15         
成    绩:                 
         
日期:  2011  年  5  月  31  日
1. 设计任务
1.1利用C语言实现BMP格式图象文件的分析和显示。主要内容包括:
a)基本任务:完成BMP格式图像的显示,要求在提供的画布上循环的显示某一文件夹下面所有的BMP文件(支持所有BMP格式)
    b)拓展任务:实现图像的特效显示(淡入淡出,百页窗等等)
1.2进度情况:
  A、我对BMP图像的了解
BMP 文件是标准的Windows位图文件,有16、256、16位真彩及24位  真彩等格式。客观存在按文件头、图像控制信息、彩表和位图点阵数据的格式来存储。文件头是定义图像文件的类型、长度等的数据结构:图像控制信息是定义图像颜格式、图像大小、颜数等的数据结构:彩表是定义图像颜的调板的数组位图点阵,是定义图像数据的数组。
未经压缩的BMP文件中,位图点阵信息是按扫描线从下至上(bottom to top)存储的,即图像的第一个像素值在位图阵列的左下角,最后一个像素值在位图阵列的右上角。对16位图,每个像素占4位,每个字节存放相邻的两个像素值,高4位存放的第1个像素值在扫描线的前面,低4位存放的第2个像素值在扫描线后面。对256位图,1个字节存放1个像素值。对24位位图,颜表为空,位图数据的每3个字节对应1个像素值,其中每个字节分别对应该像素值的P、R、G值。
B、我对于BMP图像显示平台的理解
1、通过enum{}来对各个按键(向上,向下,向左右等)作出定义
2、定义结构体T_Message,用于接收和发出信号,来控制各个函数的进度。
3、创建消息队列,用于控制各个程序的进度(即决定什么时候开始或者结束它的进程)
4、定义结构体变量T_Message    RecvMsg,用于接收从队列中发出的消息。
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模式)的图像。
2. 基本思路
通过查阅资料和自己的思考,猜想,我觉得要实现在画布上显示BMP图像,主要有以下几种方法
Ⅰ 最初的想法是可以利用描点函数GFMSetPixels,逐个显示出BMP图像的点,最终构成一幅完整的图像。具体编码后,证实这是可行的。
Ⅱ 查阅一些资料后,我了解到还可以利用粘贴函数GFMWriteRectangle。即将图像文件中的数据读取出来,用malloc动态分配内存,记录图像数据,然后将内存中数据拷贝到画布上的一个矩形框内,即实现了图像的显示。但是继续研究之后发现,这个方法涉及到将1,4,8,16,24bit图像数据修改为32bit的问题,比较复杂,所以最终还是采用了方案Ⅰ。
3. 方案设计
3.1  主要算法说明
主要方法:将不同像素的图像分别用不同的函数实现,即分别定义show1bit,show4bit,……show32bit等几个函数,再定义函数showbmp,按照需要显示的图像像素,决定调用相应的图像显示函数。这么做可以使结构比较清晰,增强代码的可读性。
具体实现方法:
Ⅰ定义信息头结构变量(其中变量包含BMP图像的文件头和信息头:文件标识“BM”,文件大小,保留位,数据偏移,信息头长度,宽度,高度,面数,像素的位数,压缩类型,位图数据大小,水平分辨率,垂直分辨率,颜数,重要颜)
Ⅱ定义函数,读取文件头和信息头
Ⅲ定义各个像素BMP图像的显示函数
  ⅰ32bit BMP图像的显示函数
      ⑴定义文件指针
      ⑵用fopen打开图像文件
      ⑶利用fseek函数将文件内部指针移到位图数据区,跳过信息头部分
      ⑷用fread函数将颜信息读取出来,存放在INT32U型的变量color中
      ⑸调用画点函数GFMSetPixels,把color中的颜信息显示在画布上
      ⑹利用双重循环,依次逐行读取颜信息,显示在画布上
      ⑺显示结束,用fclose关闭文件
 
ⅱ24bit BMP图像的显示函数
    由于24bit图像和32bit图像一样,都没用调板,所以实现过程相似,但有一点不同:
      因为24bit的颜信息占据3个字节,而32bit的颜信息为4个字节,故利用fread函数读取颜信息时,参数有所不同。
      32bit:fread(&color,4,1,fp)
      24bit:fread(&color,3,1,fp)
 
8bit未压缩BMP图像的显示函数
    由于8bit图像有调板,故应当先定义数组来存放调板的数据,然后在读取位图数据时,将数据对应的调板颜出来,作为GFMSetPixels的颜参数,描出一个点。
      ⑴定义文件指针
      ⑵定义存放调板颜数据的数组colorboard[256],定义循环变量i,j和颜变量color等
⑶用fopen打开图像文件
      ⑷利用fseek函数将文件内部指针移到调板数据区,跳过信息头部分
      ⑸使用for循环,调用fread函数读出调板数据放入数组colorboard[256]中:fread(&colorboard[i],4,1,fp);
      ⑹注意用rewind(fp)重新定位指针到文件首部
      ⑺重新使用fseek函数跳过信息头和调板数据
        fseek(fp,point->remove,0);
    ⑻双重循环,依次读出位图数据。这里1字节的数据对应调板中的一个颜,所以用fread时数据长度的参数应当设为1。
    for(i=0;i<point->bmpheight;i++)
    {
        for(j=0;j<point->bmpwidth+1;j++)
        {
            fread(&pcolor,1,1,fp);//读取一个位图数据
            color=colorboard[pcolor&0xff];//取读出的数据的一位,对应到调板的一个颜
            if(j<point->bmpwidth)
                GFMSetPixels(color,j,point->bmpheight-i,1);
           
        }
    }
      ⑼编写c语言的软件显示结束,用fclose关闭文件
  ⅳ 4bit未压缩BMP图像的显示函数
    4bit图像也有调板,也应当先定义数组来存放调板的数据,然后在读取位图数据时,将数据对应的调板颜出来,作为GFMSetPixels的颜参数,描出一个点。
但是和8bit图像略有不同的是,位图数据的4bit对应了调板中的一个颜数据,而不正好是1个字节,故应当对取出的位图数据做一些处理。
      ⑴定义文件指针
      ⑵定义存放调板颜数据的数组colorboard[16],定义循环变量i,j和颜变量color等
⑶用fopen打开图像文件
      ⑷利用fseek函数将文件内部指针移到调板数据区,跳过信息头部分
      ⑸使用for循环,调用fread函数读出调板数据放入数组colorboard[16]中:fread(&colorboard[i],4,1,fp);
      ⑹注意用rewind(fp)重新定位指针到文件首部
      ⑺重新使用fseek函数跳过信息头和调板数据
        fseek(fp,point->remove,0);
    ⑻双重循环,依次读出位图数据。这里1/2字节(即4bit)的数据对应调板中的一个颜,所以应当把得到的位图数据拆成前后两部分,分别对应到调板中的一种颜。为了取得前面的4bit,使用二进制右移运算符<<,把不需要的4bit移出;为取得后面的4bit,使用按位与运算符&,把前面的4bit置零。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。