從16位開始,不存在調色板,頂多存在一個RGBQUAD的掩碼。windows
16位位圖,我沒有拿到對應的素材,可是根據官方文檔的描述和代碼驗證後,我總結爲下:api
當biCompression爲BI_RGB時,此時是RGB555格式,不存在調色板。app
當biCompression爲BI_BITFIELDS時,16位位圖時RGB565格式,對應的32位是帶掩碼的格式,兩種都有一個RGBQUAD的數據存在於調色板。工具
24位位圖,只有BI_RGB存儲方式。測試
代碼實現以下spa
enum { bitmap_undefined, bitmap_unknown, bitmap1, bitmap4, bitmap4_RLE4, bitmap8, bitmap8_RLE8, bitmap16_RGB555, bitmap16_RGB565, bitmap24, bitmap32, bitmap32_mask};//全部bmp類型 class Bitmap { public: Bitmap(); virtual ~Bitmap(); HBITMAP BitCreate(HDC hDC, LPTSTR szFilename);//從文件載入 HBITMAP BitCreate(HDC hDC, HINSTANCE hInstance, UINT rscID);//從資源載入 PBITMAPFILEHEADER GetBitFileheader(PBYTE pBitmap = NULL);//位圖頭 PBITMAPINFOHEADER GetBitInfoheader(PBYTE pBitmap = NULL);//位圖INFO結構 LPRGBQUAD GetBitPalette(PBYTE pBitmap = NULL);//位圖畫板,不存在返回NULL PVOID GetBitData(PBYTE pBitmap = NULL);//位圖數據 void BitDraw(HDC hDC, int x, int y, HBITMAP hBitmap);//將位圖畫到本身的窗口 protected: void BitErrorshow(DWORD errorID);//錯誤提示 void BitTypedefined();//類型定義 void BitFree();//資源釋放 HBITMAP BitLoad(HDC hDC, PBYTE pBitmap = NULL);//載入的數據,轉換爲HBITMAP句柄,方便操做 private: HGLOBAL m_hGlablebitmap; HANDLE m_hFilemapping; PBYTE m_pBitmap; int m_iWidth, m_iHeight, m_iFilesize; int m_iType; };
對應的實現代碼code
Bitmap::Bitmap() { m_hFilemapping = m_hGlablebitmap = NULL; m_pBitmap = NULL; m_iFilesize = m_iWidth = m_iHeight = 0; m_iType = bitmap_undefined; } Bitmap::~Bitmap() { BitFree(); } void Bitmap::BitTypedefined() { PBITMAPINFOHEADER bInfoheader; bInfoheader = GetBitInfoheader(); m_iWidth = bInfoheader->biWidth; m_iHeight = bInfoheader->biHeight; WORD bitCount = bInfoheader->biBitCount; DWORD bitCompression = bInfoheader->biCompression; if (bitCompression == BI_RGB) { switch (bitCount) { case 1: m_iType = bitmap1; break; case 4: m_iType = bitmap4; break; case 8: m_iType = bitmap8; break; case 16: m_iType = bitmap16_RGB555; break; case 24: m_iType = bitmap24; break; case 32: m_iType = bitmap32; break; default: m_iType = bitmap_unknown; } } else if (bitCompression == BI_BITFIELDS) { switch (bitCount) { case 16: m_iType = bitmap16_RGB565; break; case 32: m_iType = bitmap32_mask; break; default: m_iType = bitmap_unknown; } } else if (bitCompression == BI_RLE4) m_iType = bitmap4_RLE4; else if (bitCompression == BI_RLE8) m_iType = bitmap8_RLE8; else m_iType = bitmap_unknown; } HBITMAP Bitmap::BitLoad(HDC hDC, PBYTE pBitmap) { PBITMAPINFOHEADER pBitmapinfo = GetBitInfoheader(pBitmap); PBYTE pBitmapdata = (PBYTE)GetBitData(pBitmap), pDIBData = NULL; HBITMAP hBitmap = CreateDIBSection(hDC, (PBITMAPINFO)pBitmapinfo, DIB_RGB_COLORS, (void **)&pDIBData, NULL, 0); DWORD sizeImage = m_iFilesize - (DWORD)(pBitmapdata - pBitmap);//永遠本身計算數據大小,由於位圖INFO頭中的biSizeImage字段可能爲0. CopyMemory(pDIBData, pBitmapdata, sizeImage); return hBitmap; } void Bitmap::BitErrorshow(DWORD errorID) { TCHAR szCaption[64]; LPVOID lpMsgBuf; wsprintf(szCaption, L"錯誤代碼:0x%08x", errorID); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, errorID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL); MessageBox(NULL, (LPTSTR)lpMsgBuf, szCaption, MB_OK | MB_ICONSTOP); LocalFree(lpMsgBuf); } HBITMAP Bitmap::BitCreate(HDC hDC, LPTSTR szFilename) { HANDLE hFile = NULL; BitFree();//釋放以前數據 __try { hFile = CreateFile(szFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); m_hFilemapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); m_pBitmap = (PBYTE)MapViewOfFile(m_hFilemapping, FILE_MAP_READ, 0, 0, 0); m_iFilesize = GetFileSize(hFile, 0); BitTypedefined(); }__except (EXCEPTION_EXECUTE_HANDLER) { BitErrorshow(GetLastError()); CloseHandle(hFile); BitFree(); return NULL; } CloseHandle(hFile); return BitLoad(hDC, m_pBitmap); } HBITMAP Bitmap::BitCreate(HDC hDC, HINSTANCE hInstance, UINT rscID) { HRSRC hResInfo = NULL; BitFree();//釋放以前數據 __try { hResInfo = FindResource(hInstance, MAKEINTRESOURCE(rscID), RT_BITMAP); m_hGlablebitmap = LoadResource(hInstance, hResInfo); m_pBitmap = (PBYTE)LockResource(m_hGlablebitmap); m_iFilesize = SizeofResource(hInstance, hResInfo); BitTypedefined(); }__except (EXCEPTION_EXECUTE_HANDLER) { BitErrorshow(GetLastError()); BitFree(); return NULL; } return BitLoad(hDC, m_pBitmap); } void Bitmap::BitFree() { if (m_hFilemapping != NULL) { UnmapViewOfFile(m_pBitmap); CloseHandle(m_hFilemapping); m_hFilemapping = NULL; } else if (m_hGlablebitmap != NULL) { UnlockResource(m_hGlablebitmap); FreeResource(m_hGlablebitmap); m_hGlablebitmap = NULL; } m_pBitmap = NULL; m_iType = bitmap_undefined; m_iFilesize = m_iHeight = m_iWidth = 0; } PBITMAPFILEHEADER Bitmap::GetBitFileheader(PBYTE pBitmap) { if (m_hFilemapping != NULL) return pBitmap ? (PBITMAPFILEHEADER)pBitmap : (PBITMAPFILEHEADER)m_pBitmap; return NULL; } PBITMAPINFOHEADER Bitmap::GetBitInfoheader(PBYTE pBitmap) { DWORD offset = 0; if (m_hFilemapping != NULL) offset = sizeof(BITMAPFILEHEADER); return pBitmap ? (PBITMAPINFOHEADER)(pBitmap + offset) : (PBITMAPINFOHEADER)(m_pBitmap + offset); } LPRGBQUAD Bitmap::GetBitPalette(PBYTE pBitmap) { PBITMAPINFOHEADER pBitmapinfo = GetBitInfoheader(pBitmap); PBYTE pPalette = (PBYTE)pBitmapinfo + sizeof(PBITMAPINFOHEADER), pData = (PBYTE)GetBitData(pBitmap); if (pPalette == pData)//不存在調色板 return NULL; return (LPRGBQUAD)pPalette; } PVOID Bitmap::GetBitData(PBYTE pBitmap) { DWORD offset = 0, n; PBITMAPINFOHEADER pBitmapinfo = GetBitInfoheader(pBitmap); n = pBitmapinfo->biClrUsed ? pBitmapinfo->biClrUsed : pBitmapinfo->biBitCount; switch (m_iType) { case bitmap1: case bitmap4: case bitmap4_RLE4: case bitmap8: case bitmap8_RLE8: offset = (DWORD)pow(2, n); break; case bitmap16_RGB565: case bitmap32_mask: offset = 1; break; } return (PBYTE)pBitmapinfo + offset * sizeof(RGBQUAD)+sizeof (BITMAPINFOHEADER); } void Bitmap::BitDraw(HDC hDC, int x, int y, HBITMAP hBitmap){ if (hBitmap != NULL) { HDC hMemDC = CreateCompatibleDC(hDC); HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);//載入位圖 BitBlt(hDC, x, y, m_iWidth, m_iHeight, hMemDC, 0, 0, SRCCOPY); SelectObject(hMemDC, hOldBitmap);//還原位圖 DeleteDC(hMemDC); } }
代碼測試圖orm
1位位圖:blog
4位位圖圖片
8位位圖
24位位圖
其餘位圖能夠隨意測試,均無問題。圖片是我隨意弄的,哈哈哈,本身用windows自帶的畫圖工具就能夠作出不一樣類型的位圖,這裏就不上傳位圖資源文件了。