用户操作
[留言]  [发消息]  [加为好友] 
订阅我的博客
XML聚合    FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
TargetStudio的公告
文章分类
    Target
    配色表
    存档

    原创  bmp 10.27 范鲁艳 收藏

          这几天一直都在忙关于 BMP 的操作问题,以前从来不知道它是个什么东东,所以感觉很吃力。到现在为止很多东西还是不明白,期间也怀疑自己能否胜任这样的学习,但是想想做什么容易那,做任何事情都是需要付出努力的啊。所以就把这些天一些微小的收获拿出来和大家共享。

         之前听祝勇讲过一次关于BMP 的课,但是那时云里雾里的不知所云,只知道是图象的一种格式包含几个部分:文件头/信息头/颜色表/位图数据。

    下面把我找到的一些资料归结一下:

    1. BMP文件组成
    BMP
    文件由文件头、位图信息头、颜色信息和图形数据四部分组成。
    2. BMP
    文件头
    BMP
    文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息。

    其结构定义如下:

    typedef struct tagBITMAPFILEHEADER
    {
    WORD   bfType; //
    位图文件的类型,必须为BM
    DWORD  bfSize; //
    位图文件的大小,以字节为单位
    WORD   bfReserved1; //
    位图文件保留字,必须为0
    WORD   bfReserved2; //
    位图文件保留字,必须为0
    DWORD  bfOffBits; //
    位图数据的起始位置,以相对于位图
    //
    文件头的偏移量表示,以字节为单位
    } BITMAPFILEHEADER;

    3.
    位图信息头

    BMP
    位图信息头数据用于说明位图的尺寸等信息。
    typedef   struct  tagBITMAPINFOHEADER{
    DWORD   biSize; //
    本结构所占用字节数
    LONG     biWidth; //
    位图的宽度,以像素为单位
    LONG     biHeight; //
    位图的高度,以像素为单位
    WORD   biPlanes; //
    目标设备的级别,必须为1
    WORD    biBitCount//
    每个像素所需的位数,必须是1(双色),
                                       // 4(16
    )8(256)24(真彩色)之一
    DWORD  biCompression; //
    位图压缩类型,必须是 0(不压缩),
                                       // 1(BI_RLE8
    压缩类型)2(BI_RLE4压缩类型)之一
    DWORD   biSizeImage; //
    位图的大小,以字节为单位
    LONG      biXPelsPerMeter; //
    位图水平分辨率,每米像素数
    LONG      biYPelsPerMeter; //
    位图垂直分辨率,每米像素数
    DWORD    biClrUsed;//
    位图实际使用的颜色表中的颜色数
    DWORD    biClrImportant;//
    位图显示过程中重要的颜色数
    } BITMAPINFOHEADER;

    4.
    颜色表
    颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个RGBQUAD类型的结构,定义一种颜色。RGBQUAD结构的定义如下:

    typedef struct tagRGBQUAD {
    BYTE   rgbBlue;//
    蓝色的亮度(值范围为0-255)
    BYTE   rgbGreen; //
    绿色的亮度(值范围为0-255)
    BYTE   rgbRed; //
    红色的亮度(值范围为0-255)
    BYTE   rgbReserved;//
    保留,必须为0
    } RGBQUAD;
    颜色表中RGBQUAD结构数据的个数有biBitCount来确定:
    biBitCount=1,4,8时,分别有2,16,256个表项;
    biBitCount=24时,没有颜色表项。
    位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下:
    typedef struct tagBITMAPINFO {
    BITMAPINFOHEADER bmiHeader; //
    位图信息头
    RGBQUAD bmiColors[1]; //
    颜色表
    } BITMAPINFO;


    5.
    位图数据
    位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。位图的一个像素值所占的字节数:

    biBitCount=1时,8个像素占1个字节;
    biBitCount=4时,2个像素占1个字节;
    biBitCount=8时,1个像素占1个字节;
    biBitCount=24,1个像素占3个字节;
    Windows
    规定一个扫描行所占的字节数必须是
    4
    的倍数(即以long为单位),不足的以0填充,
    一个扫描行所占的字节数计算方法:
    DataSizePerLine= (biWidth* biBitCount+31)/8;
    //
    一个扫描行所占的字节数
    DataSizePerLine= DataSizePerLine/4*4; //
    字节数必须是4的倍数
    位图数据的大小(不压缩情况下):
    DataSize= DataSizePerLine* biHeight;

         看了这些以后又对位图有了一些更加深入的理解,也算是收获把。

      关于位图的打开与显示问题有下面这些了解:

     


    显示一张位图,基本的有以下三种形式:  
       
     
    一、位图资源的显示(设资源IDIDB——BITMAP1程序如下)  
       
      {  
       
              CBitmap   bitmap;  
       
              CBitmap*   pOldBitmap;  
       
              CDC   MemDC;  
       
              MemDC.CreateCompatibleDC(&dc);   ///
    建立与显示设备兼容的内存设备场境  
       
              bitmap.LoadBitmap(IDB_BITMAP1);   ///
    取出位图资源  
       
              pOldBitmap=MemDC.SelectObject(&bitmap);   ///
    将位图选入内存场境  
       
              dc.BitBlt(50,50,48,48,&MemDC,0,0,SRCCOPY);   ///
    显示它  
       
              MemDC.SelectObject(pOldBitmap);  
       
      }  
     
    二、创建位图,然后在里面画上图形,再显示它  
       
      {  
       
              CBitmap   bitmap;  
       
              CBitmap*   pOldBitmap;  
       
              CDC   MemDC;  
       
              int   i;  
       
              CPen   pen;  
       
              CPen*   oldpen;  
       
              MemDC.CreateCompatibleDC(&dc);   ///
    建立与显示设备兼容的内存设备场境  
       
              bitmap.CreateCompatibleBitmap(&dc,100,100);///
    建立与显示设备兼容的位图  
       
              pOldBitmap=MemDC.SelectObject(&bitmap);   ///
    将位图选入内存场境  
       
              for(i=0;i<100;i++)  
       
              {   ///
    100根线  
       
                    pen.CreatePen(PS_SOLID,1,   RGB(0,0,i*2+55));          
       
                    oldpen=MemDC.SelectObject(&pen);  
       
                    MemDC.MoveTo(0,i);  
       
                    MemDC.LineTo(100,i);  
       
                    MemDC.SelectObject(oldpen);  
       
                    pen.DeleteObject();  
       
              }  
       
              dc.BitBlt(50,50,100,100,&MemDC,0,0,SRCCOPY);   ///
    显示它  
       
              MemDC.SelectObject(pOldBitmap);  
       
      }  
     
    三、显示磁盘上的外部BMP文件  
       
      {  
       
            HBITMAP   bitmap;  
       
            /////
    读取位图文件SAMPLE.BMP  
       
            bitmap=(HBITMAP)LoadImage(AfxGetInstanceHandle(),"SAMPLE.BMP",IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);  
       
            ASSERT(bitmap);  
       
            HBITMAP   OldBitmap;  
       
            CDC   MemDC;CRect   rect;  
       
            MemDC.CreateCompatibleDC(&dc);  
       
            GetClientRect(rect);  
       
            OldBitmap=(HBITMAP)MemDC.SelectObject(bitmap);  
       
            ///
    显示它  
       
            dc.BitBlt(20,20,rect.Width()-20,rect.Height()-20,&MemDC,0,0,SRCCOPY);  
       
            MemDC.SelectObject(OldBitmap);  
       
      }
     
     

     但是又查了一些资料说打开位图用的多的方法还有建立一个 cdib类,类里面封装了所需要的函数:

    #if !defined(AFX_FG_DIB_H__873E62A0_D6E8_4151_9F0F_815768446735__INCLUDED_)
    #define AFX_FG_DIB_H__873E62A0_D6E8_4151_9F0F_815768446735__INCLUDED_

    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000

    class CFG_DIB : public CObject 
    {
    public:
     //默认构造函数
     CFG_DIB();
     //构造函数,根据图象宽和高,以及记录每个象素所需字节数来初始化
     CFG_DIB(int width, int height, int nBitCounts);
     virtual ~CFG_DIB();

    public:
     HBITMAP m_hBitmap;
     LPBYTE m_lpDIBits;     //DIB位的起始位置
     LPBITMAPINFOHEADER m_lpBMPHdr;  //BITMAPINFOHEADER信息
     LPVOID m_lpvColorTable;    //颜色表信息
     HPALETTE m_hPalette;    //调色板
     int m_nMode;      //内存模式,0为普通模式,1为内存映射模式

    private:
     DWORD m_dwImageSize;    //非BITMAPINFOHEADER或BITMAPFILEHEADER的位
     int m_nColorEntries;    //颜色表项的个数

     HANDLE m_hFile;
     HANDLE m_hMap;
     LPVOID m_lpvFile;

    //显示参数
    public:
     CPoint m_Dest;      //目的矩形域的左上角坐标
     CSize m_DestSize;     //显示矩形的宽度和高度
     CPoint m_Src;      //原矩形左下角坐标
     CSize m_SrcSize;     //原矩形宽度和高度

    public:
     void InitDestroy();       //初始化变量
     void ComputePaletteSize(int nBitCounts); //计算调色板大小
     void ComputeImage();      //计算图象大小

     //从BMP文件中读入DIB信息
     BOOL ReadFile(CFile* pFile);
     //从BMP文件中读入DIB信息,与ReadFile不同的是使用CreateSection创建位图位
     BOOL ReadSection(CFile* pFile, CDC* pDC = NULL);
     //将DIB写入文件,保存成BMP图片格式
     BOOL WriteFile(CFile* pFile);
     //创建新的位图文件,根据参数width,height,nBitCounts分配内存空间
     BOOL NewFile(int width, int height, int nBitCounts);
     //关闭位图文件
     BOOL CloseFile();

     //显示位图
     BOOL Display(CDC* pDC);

     HBITMAP CreateBitmap(CDC* pDC);    //用DIB创建DDB
     HBITMAP CreateSection(CDC* pDC = NULL);  //创建位图位数据,即象素数据
     //如果DIB没有颜色表,可以用逻辑调色板
     BOOL SetLogPalette(CDC* pDC);
     //如果DIB有颜色表,可以创建系统调色板
     BOOL SetWinPalette();
     //把DIB对象的逻辑调色板选进设备环境里,然后实现调色板
     UINT UseLogPalette(CDC* pDC);

     //得到BitmapInfoHeader的大小,包含颜色表数据
     int GetHeaderSize()
     {
      return sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorEntries;
     }
     //得到图像的高度
     int GetHeight()
     {
      if(m_lpBMPHdr == NULL) return 0;
      return m_lpBMPHdr->biHeight;
     }
     //得到图像的宽度
     int GetWidth()
     {
      if(m_lpBMPHdr == NULL) return 0;
      return m_lpBMPHdr->biWidth;
     }
     //得到图像的大小
     int GetImageSize()
     {
      return m_dwImageSize;
     }
     long GetLineBit();  //得到一行的象素数
     void SetMode(int mode); //设置内存模式
     void ReleaseMapFile(); //释放内存映射文件
    };

    #endif // !defined(AFX_FG_DIB_H__873E62A0_D6E8_4151_9F0F_815768446735__INCLUDED_)

    心里很郁闷啊任务还没有完成,不说了 ,今天就写到这里!!希望大家多帮助!!在此先谢过了!!

    发表于 @ 2006年10月27日 17:46:00 | 评论( loading... ) | 编辑| 举报| 收藏

    旧一篇:VC++ListCtrl控件(陆) | 新一篇:用分水岭算法实现图像分割 (祝勇)

    • 发表评论
    • 评论内容:
    •  
    Copyright © TargetStudio
    Powered by CSDN Blog