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;

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

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

 


显示一张位图,基本的有以下三种形式:  
   
 
一、位图资源的显示(设资源 ID IDB——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_)

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值