我寫了壹個簡單的創建24位BMP位圖的小程序。 簡單演示了bmp位圖的格式。
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#define BMP_W 640L
#define BMP_H 480L
void SetBmpInfoHeader(PBITMAPINFOHEADER pbmpih)
{
/* 14~17: 本結構體所占字節數, 固定值40 */
pbmpih->biSize = 40;
/* 18~21: 位圖的寬度(以像素pixel為單位) */
pbmpih->biWidth = BMP_W;
/* 22~25: 位圖的高度 */
pbmpih->biHeight = BMP_H;
/* 26~27: 目標設備的級別, 固定值:1 */
pbmpih->biPlanes = 1;
/* 28~29: 壹個像素所占bit數, 可以是:1(雙色)、4(16色)、8(256色)
、16(65536色)、24(真彩色2^24種顏色)、32(真彩色2^32種顏色),具體參閱MSDN。
對於24位真彩色位圖, 壹個像素占用三個字節,即24 bits */
pbmpih->biBitCount = 24;
/* 30~33:指定是否壓縮, (如果壓縮了)采用的壓縮格式。
可以為: BI_RGB、BI_RLE4、BI_RLE8、BI_BITFIELDS、BI_PNG、BI_JPEG
有的位圖會進行遊程長度編碼:BI_RLE4、BI_RLE8
壓縮可以節省空間, 但不便於編程讀寫。BI_RGB表示不進行壓縮處理 */
pbmpih->biCompression = BI_RGB;
/* 34~37: 位圖數據區所占字節數,有固定的計算公式 */
pbmpih->biSizeImage = ((((pbmpih->biWidth * pbmpih->biBitCount) + 31) & ~31) / 8) * pbmpih->biHeight;
/* 38~41: 位圖水平分辨率,每米像素數 */
pbmpih->biXPelsPerMeter = 0L;
/* 42~45: 位圖垂直分辨率,每米像素數 */
pbmpih->biYPelsPerMeter = 0L;
/* 46~49: 位圖實際使用顏色表中顏色數(對於有調色板的位圖來說實際上是調色板中顏色項數,
24位真彩色位圖不需要調色板, 設為0, 8位灰度位圖為256(2^8種顏色)。 */
pbmpih->biClrUsed = 0L;
/* 50~53: 顯示位圖所需顏色數 */
pbmpih->biClrImportant = 0L;
}
void SetBmpFileHeader(PBITMAPFILEHEADER pbmpfh, const PBITMAPINFOHEADER pbmpih)
{
/* 0~1: 固定值: "BM"(或0x4D42),即表明這是位圖(壹般以bmp為文件名後綴)*/
pbmpfh->bfType = *(WORD *)"BM";
/* 2~5: 位圖文件總大小(占用總字節數, 包括文件頭、信息頭、調色板、位圖數據區占用字節數)*/
pbmpfh->bfSize = pbmpih->biSizeImage + 54 + pbmpih->biClrUsed * sizeof(RGBQUAD);
/* 6~7: 固定值0: 目前沒什麽用, 可能留作將來擴展。也有的結構體中有這樣的域是為了內存對齊 */
pbmpfh->bfReserved1 = 0;
/* 8~9: 固定值 */
pbmpfh->bfReserved2 = 0;
/* 10~13: 位圖數據區起始位置, 計算方法為:
位圖文件頭14個字節+位圖信息頭40個字節+位圖調色板所占字節數,
這裏要創建的是壹張24位位圖(無調色板),故設置為54 也可以。*/
pbmpfh->bfOffBits = 54 + pbmpih->biClrUsed * sizeof(RGBQUAD);
}
int main(void)
{
BITMAPFILEHEADER bmpfh = { 0 }; /* 位圖文件頭 */
BITMAPINFOHEADER bmpih = { 0 }; /* 位圖信息頭 */
FILE *fpBmp = NULL;
COLORREF color = RGB(0xf0,0xca,0xa6); /* 天藍色 */
COLORREF black = 0;
int fillbits;
int w, h;
SetBmpInfoHeader(&bmpih);
SetBmpFileHeader(&bmpfh, &bmpih);
fillbits = ( 4 - ( bmpih.biWidth * 3 ) % 4 ) % 4;
fpBmp = fopen("D:\\rendering.bmp", "wb");
if (NULL == fpBmp) {
perror("fopen failed:");
system("pause>nul");
exit(EXIT_FAILURE);
}
fwrite(&bmpfh, sizeof(BITMAPFILEHEADER), 1, fpBmp); /* 寫入位圖文件頭 */
fwrite(&bmpih, sizeof(BITMAPINFOHEADER), 1, fpBmp); /* 寫入位圖信息頭 */
/* 寫入調色板(如果有的話) */
/* 寫入位圖數據 */
for (h = 0; h < BMP_H; ++h) {
for (w = 0; w < BMP_W; ++w) {
fwrite(&color, 3, 1, fpBmp); /* 將像素值顏色寫入位圖文件 */
}
/* 邊界填充
對於24位位圖每個像素占3個字節,且每個掃描行所占字節數必須是4的倍數。
比如,對於壹張寬度為21個像素的24色位圖, 理論上每掃描行占用21*3=63個字節,
但63不是4的倍數,所以需要在該掃描行的最後填充壹個字節的0,湊到64,
這樣實際上每掃描行占用64個字節。
fillbits = ( 4 - ( biheader.biWidth * 3 ) % 4 ) % 4; 參考自acepig, 作用是
計算每掃描行需要填充幾個字節的0。對於寬度是4的倍數的圖片, count為0。
*/
fwrite(&black, 1, fillbits, fpBmp);
}
fclose(fpBmp);
system("mspaint D:\\rendering.bmp");
return 0;
}