头文件Cdib.h
#ifndef __CDIB_H #define __CDIB_H class CDib : public CObject { public: BITMAPFILEHEADER bitmapFileHeader;//位图文件头结构 BYTE* pDib;//指向位图文件内容的指针 DWORD size;//位图信息大小 BITMAPINFO* m_pBitmapInfo;//指向位图信息的指针 BITMAPINFOHEADER* m_pBitmapInfoHeader;//指向位图信息头的指针 RGBQUAD* m_pPalette;//指向调色板的指针 BYTE* m_pData;//指向位图数据的指针 BOOL m_valid;//判断是否是位图文件 CPalette m_Palette;//调色板对象 int m_nPaletteEntries;//调色板颜色数目 int m_WIDTHBYTES;//字节宽 public: CDib(); ~CDib(); DWORD GetSize();//获得图像数据大小,以字节为单位 void DrawImage(CPaintDC* dc,int left,int top,int right,int bottom);//绘制图像 void LoadFile(CString filePath);//加载位图文件 void SaveFile(CString filePath);//保存位图文件 }; #endif
源文件Cdib.cpp
#include "stdafx.h" #include "cdib.h" #include "windowsx.h" #include "math.h" #define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4) CDib::CDib() { size=0;//位图信息大小 } CDib::~CDib() { GlobalFreePtr(pDib);//释放内存 } //加载位图数据 void CDib::LoadFile(CString filePath) { CFile dibFile(filePath, CFile::modeRead);//通过文件路径创建一个文件 dibFile.Read((void*)&bitmapFileHeader,sizeof(BITMAPFILEHEADER));//读取文件头到文件头结构 if (bitmapFileHeader.bfType == 0x4d42)//判断文件类型是否是位图文件 { DWORD fileLength = dibFile.GetLength();//获得文件大小 size = fileLength -sizeof(BITMAPFILEHEADER);//获得位图信息大小 pDib = (BYTE*)GlobalAllocPtr(GMEM_MOVEABLE, size);//分配一大小为size的可移动内存块 dibFile.Read((void*)pDib, size);//将数据读取到位图信息指针所指向的内存 dibFile.Close();//关闭位图文件 m_pBitmapInfo = (BITMAPINFO*) pDib;//获取位图信息指针 m_pBitmapInfoHeader = (BITMAPINFOHEADER*) pDib;//获取位图信息头指针 m_pPalette = (RGBQUAD*)(pDib + m_pBitmapInfoHeader->biSize);//获得位图颜色表指针 m_pBitmapInfoHeader->biSizeImage = GetSize();//获得位图数据大小 // 计算调色板中实际颜色数量 m_nPaletteEntries = 1 << m_pBitmapInfoHeader->biBitCount;//逻辑值 //实际值 if( m_pBitmapInfoHeader->biBitCount > 8 ) { m_nPaletteEntries = 0; } else if( m_pBitmapInfoHeader->biClrUsed != 0 ) { m_nPaletteEntries = m_pBitmapInfoHeader->biClrUsed; } DWORD colorTableSize = m_nPaletteEntries * sizeof(RGBQUAD);//颜色表大小 m_pData = pDib + m_pBitmapInfoHeader->biSize + colorTableSize;//获得位图数据的指针 if (m_pPalette == (RGBQUAD*)m_pData)//没有调色板的情况 { m_pPalette = NULL; } else//有调色板的情况,创建调色板对象 { // 重置全局调色板 if( m_Palette.GetSafeHandle() != NULL ) { m_Palette.DeleteObject(); } //为逻辑调色板分配内存,通过逻辑调色板创建调色板 LOGPALETTE *pLogPal = (LOGPALETTE *) new char [sizeof(LOGPALETTE)+ m_nPaletteEntries*sizeof(PALETTEENTRY)]; if( pLogPal != NULL ){ //设置逻辑调色板的版本 pLogPal->palVersion = 0x300; //设置逻辑调色板的颜色数量 pLogPal->palNumEntries = m_nPaletteEntries; //为每个颜色实体赋颜色值 for( int i=0; i<m_nPaletteEntries; i++ ){ pLogPal->palPalEntry[i].peRed = m_pPalette[i].rgbRed; pLogPal->palPalEntry[i].peGreen = m_pPalette[i].rgbGreen; pLogPal->palPalEntry[i].peBlue = m_pPalette[i].rgbBlue; } //创建调色板 m_Palette.CreatePalette( pLogPal ); //释放内存 delete [] pLogPal; } } m_WIDTHBYTES = WIDTHBYTES((m_pBitmapInfoHeader->biWidth)*((DWORD)m_pBitmapInfoHeader->biBitCount)); m_valid = TRUE;//位图文件读取成功 } else { m_valid = FALSE;//位图文件读取失败 } } //获得图像数据大小,以字节为单位 DWORD CDib::GetSize() { if (m_pBitmapInfoHeader->biSizeImage != 0) { return m_pBitmapInfoHeader->biSizeImage; } else { return WIDTHBYTES((m_pBitmapInfoHeader->biWidth)*((DWORD)m_pBitmapInfoHeader->biBitCount))*m_pBitmapInfoHeader->biHeight; } } //保存位图文件 void CDib::SaveFile(CString filePath) { CFile dibFile(filePath, CFile::modeCreate|CFile::modeWrite); dibFile.Write((void*)&bitmapFileHeader,sizeof(BITMAPFILEHEADER)); dibFile.Write((void*)pDib, size); dibFile.Close(); } //绘制图像 void CDib::DrawImage(CPaintDC* dc,int left,int top,int right,int bottom) { //如果有调色板则使用调色板 if(m_Palette.GetSafeHandle()!=NULL) { CPalette *pOldPalette; pOldPalette = dc->SelectPalette( &m_Palette, FALSE );//选择调色板 dc->RealizePalette();//实现调色板 //绘图 StretchDIBits( dc->m_hDC, left, top, right,bottom, 0, 0, m_pBitmapInfoHeader->biWidth,m_pBitmapInfoHeader->biHeight, m_pData, (BITMAPINFO *) m_pBitmapInfo, BI_RGB, SRCCOPY ); //恢复调色板 dc->SelectPalette( pOldPalette, FALSE ); } else//没有调色板,直接绘制 { StretchDIBits( dc->m_hDC, left, top, right,bottom, 0, 0, m_pBitmapInfoHeader->biWidth,m_pBitmapInfoHeader->biHeight, m_pData, (BITMAPINFO *) m_pBitmapInfo, BI_RGB, SRCCOPY ); } }