位图文件结构及MFC显示

本文详细解析了位图文件结构,包括位图文件头、位图信息头和位图数据等内容,并介绍了如何利用MFC进行位图文件的加载及显示。

一、位图文件结构

位图文件由三部分组成:文件头 + 位图信息 + 位图像素数据。

1、位图文件头。位图文件头主要用于识别位图文件。以下是位图文件头结构的定义:

 
  1. typedef struct tagBITMAPFILEHEADER { // bmfh   
  2.     WORD    bfType;   
  3.     DWORD   bfSize;   
  4.     WORD    bfReserved1;   
  5.     WORD    bfReserved2;   
  6.     DWORD   bfOffBits;   
  7. } BITMAPFILEHEADER;  

其中的bfType值应该是“BM”(0x4d42),标志该文件是位图文件。bfSize的值是位图文件的大小。


2、位图信息。位图信息中所记录的值用于分配内存,设置调色板信息,读取像素值等。
以下是位图信息结构的定义:

 
  1. typedef struct tagBITMAPINFO {  
  2.     BITMAPINFOHEADER    bmiHeader;  
  3.     RGBQUAD             bmiColors[1];  
  4. } BITMAPINFO;  

可见位图信息也是由两部分组成的:位图信息头 + 颜色表。


2.1位图信息头。位图信息头包含了单个像素所用字节数以及描述颜色的格式,此外还包括位图的宽度、高度、目标设备的位平面数、图像的压缩格式。以下是位图信息头结构的定义:
 
  1. typedef struct tagBITMAPINFOHEADER{ // bmih   
  2.     DWORD  biSize;   
  3.     LONG   biWidth;   
  4.     LONG   biHeight;   
  5.     WORD   biPlanes;   
  6.     WORD   biBitCount   
  7.     DWORD  biCompression;   
  8.     DWORD  biSizeImage;   
  9.     LONG   biXPelsPerMeter;   
  10.     LONG   biYPelsPerMeter;   
  11.     DWORD  biClrUsed;   
  12.     DWORD  biClrImportant;   
  13. } BITMAPINFOHEADER;   

下表是对结构体当中各个成员的说明: 


结构成员说 明
biSize结构BITMAPINFOHEADER的字节数,即sizeof(BITMAPINFOHEADER)*
biWidth以像素为单位的图像宽度*
biHeight以像素为单位的图像长度*
biplanes目标设备的位平面数
biBitCount每个像素的位数*(1)
biCompression图像的压缩格式(这个值几乎总是为0)
biSizeImage以字节为单位的图像数据的大小(对BI_RGB压缩方式而言)
biXPelsPermeter水平方向上的每米的像素个数
biYpelsPerMeter垂直方向上的每米的像素个数
biClrused调色板中实际使用的颜色数(2)
biClrImportant现实位图时必须的颜色数(3)


说明:*是需要加以注意的部分,因为它们是我们在进行位图操作时经常参考的变量
(1)对于每个像素的字节数,分别有一下意义:
0,用在JPEG格式中
1,单色图,调色板中含有两种颜色,也就是我们通常说的黑白图片
4,16色图
8,256色图,通常说的灰度图
16,64K图,一般没有调色板,图像数据中每两个字节表示一个像素,5个或6个位表示一个RGB分量
24,16M真彩色图,一般没有调色板,图像数据中每3个字节表示一个像素,每个字节表示一个RGB分量
32,4G真彩色,一般没有调色板,每4个字节表示一个像素,相对24位真彩图而言,加入了一个透明度,即RGBA模式

(2)这个值通常为0,表示使用biBitCount确定的全部颜色,例外是使用的颜色树木小于制定的颜色深度的颜色数目的最大值。

(3)这个值通常为0,表示所有的颜色都是必需的

2.2颜色表。颜色表一般是针对16位一下的图像而设置的,对于16位和16位以上的图像,由于其位图像素数据中直接对对应像素的RGB(A)颜色进行描述,因而省却了调色板。而对于16位一下的图像,由于其位图像素数据中记录的只是调色板索引值,因而需要根据这个索引到调色板去取得相应的RGB(A)颜色。颜色表的作用就是创建调色板。


颜色表是由颜色表项组成的,颜色表项结构的定义如下:

  1. typedef struct tagRGBQUAD { // rgbq   
  2.     BYTE    rgbBlue;   
  3.     BYTE    rgbGreen;   
  4.     BYTE    rgbRed;   
  5.     BYTE    rgbReserved;   
  6. } RGBQUAD;  

其中需要注意的问题是,RGBQUAD结构中的颜色顺序是BGR,而不是平常的RGB。


3、位图数据。最后,在位图文件头、位图信息头、位图颜色表之后,便是位图的主体部分:位图数据。根据不同的位图,位图数据所占据的字节数也是不同的,比如,对于8位位图,每个字节代表了一个像素,对于16位位图,每两个字节代表了一个像素,对于24位位图,每三个字节代表了一个像素,对于32位位图,每四个字节代表了一个像素。


二、位图文件MFC显示

1、通过点击浏览按钮选择BMP图像文件
点击浏览按钮打开文件对话框选择BMP图像文件,得到文件所在的路径目录。
关键代码如下:

void CShowBMPDlg::OnButtonSelectiamge() 
{

    char  szFilter[] = "BMP Files (*.bmp)|*.bmp|All Files (*.*)|*.*||";
    CFileDialog dlg( TRUE,"BMP",NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,szFilter );
    if(dlg.DoModal() == IDOK)
    {
        strPathName = dlg.GetPathName();        
        LoadShowBMPFile(strPathName);    
        m_hBitmap = BufferToHBITMAP();    
        Invalidate();
    }
}

2、加载BMP文件到内存
通过得到的BMP图像文件路径目录,加载BMP图像文件到内存中。
关键代码如下:

BOOL CShowBMPDlg::LoadShowBMPFile(const char *pPathname)
{
    CFile file;
    if( !file.Open( pPathname, CFile::modeRead) )
        return FALSE;
    DWORD            m_nFileLen;
    m_nFileLen = file.GetLength();
    m_pBMPBuffer = new char[m_nFileLen + 1];
    if(!m_pBMPBuffer)
        return FALSE;
    if(file.Read(m_pBMPBuffer,m_nFileLen) != m_nFileLen)
        return FALSE;
    return TRUE;
}

3、将内存中的BMP文件内容转换到HBITMAP
将内存中的BMP文件内容转换成位图句柄。
关键代码如下:

HBITMAP CShowBMPDlg::BufferToHBITMAP()

{

HBITMAP         hShowBMP;

LPSTR                hDIB,lpBuffer = m_pBMPBuffer;

LPVOID            lpDIBBits;

BITMAPFILEHEADER    bmfHeader;

DWORD           bmfHeaderLen;

bmfHeaderLen = sizeof(bmfHeader);

strncpy((LPSTR)&bmfHeader,(LPSTR)lpBuffer,bmfHeaderLen);

if (bmfHeader.bfType != (*(WORD*)"BM")) 

return NULL;
    hDIB = lpBuffer + bmfHeaderLen;

BITMAPINFOHEADER &bmiHeader = *(LPBITMAPINFOHEADER)hDIB ;

BITMAPINFO &bmInfo = *(LPBITMAPINFO)hDIB ;

m_bmW = bmiHeader.biWidth;

m_bmH = bmiHeader.biHeight;

lpDIBBits=(lpBuffer)+((BITMAPFILEHEADER *)lpBuffer)->bfOffBits;

CClientDC dc(this);

hShowBMP = CreateDIBitmap(dc.m_hDC,&bmiHeader,CBM_INIT,lpDIBBits,&bmInfo,DIB_RGB_COLORS);

    return hShowBMP;
}

4、在屏幕上显示BMP图像
双缓冲实现BMP位图显示在屏幕上。
关键代码如下:

void CShowBMPDlg::DrawImage(int x, int y, CDC *pDC)
{
    HBITMAP OldBitmap;
    CDC MemDC;
    MemDC.CreateCompatibleDC(pDC);
    OldBitmap=(HBITMAP)MemDC.SelectObject(m_hBitmap);
    CBitmap* pBitmap = CBitmap::FromHandle(m_hBitmap);
    if(m_bmW == 0 || m_bmH == 0)
        return ;
    CRect rect;
    GetClientRect(&rect);       
    pDC->BitBlt(x,y,rect.Width(),rect.Height(),&MemDC,0,0,SRCCOPY);
    GetRGB(MemDC);
    MemDC.SelectObject(OldBitmap);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值