转自:http://blog.csdn.net/sjiang2142/article/details/6445082
一、位图文件结构
位图文件由三部分组成:文件头 + 位图信息 + 位图像素数据
1、位图文件头。位图文件头主要用于识别位图文件。以下是位图文件头结构的定义:
- typedef struct tagBITMAPFILEHEADER {
- WORD bfType;
- DWORD bfSize;
- WORD bfReserved1;
- WORD bfReserved2;
- DWORD bfOffBits;
- } BITMAPFILEHEADER;
其中的bfType值应该是“BM”(0x4d42),标志该文件是位图文件。bfSize的值是位图文件的大小。
2、位图信息中所记录的值用于分配内存,设置调色板信息,读取像素值等。
以下是位图信息结构的定义:
- typedef struct tagBITMAPINFO {
- BITMAPINFOHEADER bmiHeader;
- RGBQUAD bmiColors[1];
- } BITMAPINFO;
可见位图信息也是由两部分组成的:位图信息头 + 颜色表
2.1位图信息头。位图信息头包含了单个像素所用字节数以及描述颜色的格式,此外还包括位图的宽度、高度、目标设备的位平面数、图像的压缩格式。以下是位图信息头结构的定义:
- typedef struct tagBITMAPINFOHEADER{
- DWORD biSize;
- LONG biWidth;
- LONG biHeight;
- WORD biPlanes;
- WORD biBitCount
- DWORD biCompression;
- DWORD biSizeImage;
- LONG biXPelsPerMeter;
- LONG biYPelsPerMeter;
- DWORD biClrUsed;
- DWORD biClrImportant;
- } 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 {
- BYTE rgbBlue;
- BYTE rgbGreen;
- BYTE rgbRed;
- BYTE rgbReserved;
- } RGBQUAD;
其中需要注意的问题是,RGBQUAD结构中的颜色顺序是BGR,而不是平常的RGB。
3、位图数据。最后,在位图文件头、位图信息头、位图颜色表之后,便是位图的主体部分:位图数据。根据不同的位图,位图数据所占据的字节数也是不同的,比如,对于8位位图,每个字
节代表了一个像素,对于16位位图,每两个字节代表了一个像素,对于24位位图,每三个字节代表了一个像素,对于32位位图,每四个字节代表了一个像素
二、位图文件的读取、保存和显示
头文件中定义
- private:
- DWORD m_dwDibSize;
- CPalette m_Palette;
- int m_nPaletteEntries;
- RGBQUAD *m_pPalette;
- unsigned char *m_pDib, *m_pDibBits;
- BITMAPINFOHEADER *m_pBIH;
1、读取位图
2、保存位图
-
- void CImageDisposeDlg::OnBtnsave()
- {
-
-
- CString pszFilename;
-
-
- CFileDialog hFileDlg(FALSE,"bmp",
- NULL,
- OFN_FILEMUSTEXIST|OFN_READONLY|OFN_PATHMUSTEXIST|OFN_NOCHANGEDIR,
- TEXT("BMP (*.bmp)|*.bmp|所有文件(*.*)|*.*|"),
- NULL);
-
- if(hFileDlg.DoModal() == IDOK)
- {
-
- pszFilename=hFileDlg.GetPathName();
- }
-
-
- if( m_pDib == NULL )
- return;
-
-
- CFile cf;
-
-
- if( !cf.Open( pszFilename,
- CFile::modeCreate | CFile::modeWrite ) )
- return;
-
-
- try{
-
-
- BITMAPFILEHEADER BFH;
- memset( &BFH, 0, sizeof( BITMAPFILEHEADER ) );
- BFH.bfType = 'MB';
- BFH.bfSize = sizeof( BITMAPFILEHEADER ) + m_dwDibSize;
- BFH.bfOffBits = sizeof( BITMAPFILEHEADER ) +
- sizeof( BITMAPINFOHEADER ) +
- m_nPaletteEntries * sizeof( RGBQUAD );
-
-
- cf.Write( &BFH, sizeof( BITMAPFILEHEADER ) );
- cf.Write( m_pDib, m_dwDibSize );
- }
- catch( CFileException *e ){
- e->Delete();
- return;
- }
-
- }
3、显示位图
- void CImageDisposeDlg::OnPaint()
- {
-
- CPaintDC dc(this);
-
-
- if( m_pDib == NULL )
- return;
-
-
- int nWidth,nHeight;
- nWidth = m_pBIH->biWidth;
- nHeight = m_pBIH->biHeight;
-
-
- if( m_Palette.GetSafeHandle() != NULL )
- {
- CPalette *pOldPalette;
- pOldPalette = dc.SelectPalette( &m_Palette, FALSE );
- dc.RealizePalette();
-
-
- StretchDIBits( dc.m_hDC, 0, 0,
- nWidth, nHeight,
- 0, 0,
- m_pBIH->biWidth, m_pBIH->biHeight,
- m_pDibBits,
- (BITMAPINFO *) m_pBIH,
- BI_RGB, SRCCOPY );
-
-
- dc.SelectPalette( pOldPalette, FALSE );
- }
- else
- {
- StretchDIBits( dc.m_hDC, 0, 0,
- nWidth, nHeight,
- 0, 0,
- m_pBIH->biWidth, m_pBIH->biHeight,
- m_pDibBits,
- (BITMAPINFO *) m_pBIH,
- BI_RGB, SRCCOPY );
- }
- }