方法一:CBitmap::GetBitmap (MFC 封裝)
CBitmap bitmap;
bitmap.LoadBitmap(IDB_MYBITMAP); // 或 Attach(hBitmap)
BITMAP bm;
bitmap.GetBitmap(&bm); // 填充 BITMAP 結構
int width = bm.bmWidth;
int height = bm.bmHeight;
// bm.bmWidthBytes: 每掃描列位元組數 (含對齊)
// bm.bmPlanes, bm.bmBitsPixel: 色深資訊
// bm.bmBits: 像素指標 (若為 DIB Section)
方法二:::GetObject (Win32 API, 適用純 HBITMAP)
HBITMAP hBmp = (HBITMAP)LoadImage(NULL, _T("image.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
BITMAP bm;
::GetObject(hBmp, sizeof(BITMAP), &bm);
int width = bm.bmWidth;
int height = bm.bmHeight;
// 不需建立 CBitmap 物件,輕量級
方法三:解析 BMP 檔案頭 (不載入像素資料,最快)
int GetBmpDimensions(LPCTSTR szFile, int& width, int& height) {
CFile file;
if (!file.Open(szFile, CFile::modeRead | CFile::shareDenyNone)) return -1;
BITMAPFILEHEADER bmf;
if (file.Read(&bmf, sizeof(bmf)) != sizeof(bmf)) return -1;
if (bmf.bfType != 0x4D42) return -1; // 'BM'
BITMAPINFOHEADER bmi;
if (file.Read(&bmi, sizeof(bmi)) != sizeof(bmi)) return -1;
width = bmi.biWidth;
height = abs(bmi.biHeight); // 可能為負 (頂向下)
return 0;
}
比較與選擇
| 方法 | 適用場景 | 優點 | 缺點 |
| CBitmap::GetBitmap | 已有 CBitmap 物件 (資源載入、建立相容位圖) | MFC 風格、可取得完整 BITMAP 結構 | 需建立/附加 CBitmap |
| ::GetObject | 持有 HBITMAP (LoadImage、其他 API 取得) | 輕量、無 MFC 依賴 | 需手動管理 HBITMAP 生命週期 |
| 解析檔案頭 | 僅需尺寸、不想載入像素、批次掃描大量檔案 | 最快、記憶體占用極低 | 僅限 BMP 檔案、不支援其他格式 (JPG/PNG) |
注意事項
bm.bmHeight 為正表示底向上 DIB,負表示頂向下 DIB。顯示高度取絕對值。
CBitmap::LoadBitmap 載入資源位圖時,實際建立的是 **裝置相關位圖 (DDB)**,bm.bmBits 為 NULL。若需存取像素,需建立 **DIB Section** (CreateDIBSection)。
- 高 DPI 下,
GetObject 返回邏輯像素尺寸,實際螢幕繪製可能經過縮放。