首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Windows BMP 圖片儲存完整實作:位圖檔頭、資訊頭、像素資料寫入詳解

     編輯:關於C語言

Windows BMP 圖片儲存完整實作:位圖檔頭、資訊頭、像素資料寫入詳解

BMP 是 Windows 原生無壓縮位圖格式,結構簡單、相容性佳。本文提供可直接生產使用的 C 函數,詳細解析 BITMAPFILEHEADER、BITMAPINFOHEADER 各欄位含義、對齊陷阱與跨平台注意事項。

BMP 檔案結構總覽

+------------------------+
| BITMAPFILEHEADER (14B) |  檔案類型、大小、資料偏移
+------------------------+
| BITMAPINFOHEADER (40B) |  寬高、位深、壓縮、解析度
+------------------------+
| 像素資料 (width*height*3) |  BGR 順序,每行 4 位元組對齊
+------------------------+

核心儲存函數

#include   // BITMAPFILEHEADER, BITMAPINFOHEADER
#include 
#include 

typedef unsigned char uchar;

void savebmp(uchar *pdata, const char *bmp_file, int width, int height) {
    // 1. 計算資料大小(24-bit RGB,每像素 3 位元組)
    int row_stride = ((width * 3 + 3) / 4) * 4;  // 每行 4 位元組對齊
    int data_size = row_stride * height;

    // 2. 填充檔案頭
    BITMAPFILEHEADER bfh = {0};
    bfh.bfType = 0x4D42;  // 'BM'
    bfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + data_size;
    bfh.bfReserved1 = 0;
    bfh.bfReserved2 = 0;
    bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

    // 3. 填充資訊頭
    BITMAPINFOHEADER bih = {0};
    bih.biSize = sizeof(BITMAPINFOHEADER);
    bih.biWidth = width;
    bih.biHeight = -height;  // 負高度 = 自上而下 (Top-down DIB),避免圖片倒置
    bih.biPlanes = 1;
    bih.biBitCount = 24;     // 24-bit RGB
    bih.biCompression = BI_RGB; // 不壓縮
    bih.biSizeImage = data_size;
    bih.biXPelsPerMeter = 2835; // 72 DPI ≈ 2835 px/m
    bih.biYPelsPerMeter = 2835;
    bih.biClrUsed = 0;
    bih.biClrImportant = 0;

    // 4. 寫入檔案
    FILE *fp = fopen(bmp_file, "wb");
    if (!fp) return;

    fwrite(&bfh, sizeof(bfh), 1, fp);
    fwrite(&bih, sizeof(bih), 1, fp);
    fwrite(pdata, data_size, 1, fp);
    fclose(fp);
}

關鍵技術點深度解析

1. 行對齊

BMP 規定每掃描行大小必須是 4 位元組倍數。

int row_stride = ((width * 3 + 3) / 4) * 4;  // 向上取整到 4 的倍數

例如寬度 10:10×3=30 → 對齊為 32 位元組,每行補 2 位元組填充。

2. 負高度避免圖片倒置

BMP 預設從左下角開始掃描(Bottom-up)。設定 biHeight = -height 宣告為 Top-down DIB,像素資料按從上到下順序存放,直接對應常規影像陣列 data[y*width + x],免去垂直翻轉。

3. 位元順序:BGR 而非 RGB

24-bit BMP 像素順序為 Blue, Green, Red。輸入資料若為 RGB,寫入前需交換 R/B 通道:

for (int i = 0; i < width * height; ++i) {
    uchar tmp = pdata[i*3];
    pdata[i*3] = pdata[i*3+2];
    pdata[i*3+2] = tmp;
}

4. 跨平台結構體對齊陷阱

Linux/GCC 預設 4 位元組對齊,sizeof(BITMAPFILEHEADER) 可能為 16 而非 14。解決方案:

#pragma pack(push, 1)
typedef struct { ... } BITMAPFILEHEADER;
#pragma pack(pop)
// 或使用 __attribute__((packed)) (GCC/Clang)

完整範例:產生漸層測試圖

int main() {
    int w = 256, h = 256;
    uchar *img = malloc(w * h * 3);
    for (int y = 0; y < h; ++y)
        for (int x = 0; x < w; ++x) {
            int idx = (y * w + x) * 3;
            img[idx] = x;       // B
            img[idx+1] = y;     // G
            img[idx+2] = (x+y)/2; // R
        }
    savebmp(img, "gradient.bmp", w, h);
    free(img);
    return 0;
}

常見錯誤排查表

現象原因修正
圖片倒置biHeight 為正設為 -height
顏色錯亂(紅藍互換)RGB 順序寫入轉換為 BGR
右側有雜訊條紋未處理行對齊計算 row_stride,寫入時補齊
檔案無法開啟bfSize/bfOffBits 計算錯嚴格按結構體大小+資料大小計算
Linux 下寫入損壞結構體對齊導致頭部膨脹加 #pragma pack(1)

掌握 BMP 格式細節,不僅能實現零依賴影像輸出,更能深入理解位圖資料在記憶體與磁碟上的真實佈局,為圖形程式打下堅實基礎。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved