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

C 語言實作 BMP 影像右旋 90 度(單色位圖)

     編輯:關於C語言

BMP 檔案結構速覽

  • File Header(14 bytes):bfType='BM'、檔案大小、資料偏移量。
  • Info Header(40 bytes):寬、高、位深(biBitCount)、壓縮方式、影像大小等。
  • 調色盤:單色圖(1 bit)僅 2 色,佔 8 bytes。
  • 像素資料:每行補齊至 4 位元組邊界(stride = (width+31)/32*4)。

旋轉邏輯

原圖 W×H,旋轉後變 H×W。單色圖每像素 1 bit,需逐 bit 讀取、重新排列、打包寫入。本程式分四階段:

  1. 解碼:將位元組展開為 first[H×W],每元素 0/1。
  2. 旋轉:second[new_row][new_col] = first[old_row][old_col],對應 second[i][j] = first[W-1-j][i]。
  3. 補零:新行寬需補齊至 32 位元組倍數,third 補 0。
  4. 打包:每 8 bit 合成一 byte 存入 forth,寫入檔案。

完整程式碼(關鍵片段)

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

typedef unsigned short WORD;
typedef unsigned int DWORD;
typedef unsigned int LONG; // 注意:64 位系統建議改 typedef long LONG

#pragma pack(2)
typedef struct { WORD bfType; DWORD bfSize; WORD bfReserved1, bfReserved2; DWORD bfOffBits; } BITMAPFILEHEADER;
#pragma pack()
typedef struct { DWORD biSize; LONG biWidth, biHeight; WORD biPlanes, biBitCount; DWORD biCompression, biSizeImage; LONG biXPelsPerMeter, biYPelsPerMeter; DWORD biClrUsed, biClrImportant; } BITMAPINFOHEADER;

void cw90(const char *in, const char *out) {
    FILE *f = fopen(in, "rb"); if (!f) { perror(in); return; }
    BITMAPFILEHEADER fh; BITMAPINFOHEADER ih;
    fread(&fh, sizeof fh, 1, f);
    fread(&ih, sizeof ih, 1, f);
    unsigned char palette[8]; fread(palette, 1, 8, f);
    unsigned char *data = malloc(ih.biSizeImage);
    fread(data, 1, ih.biSizeImage, f);
    fclose(f);

    // 新影像參數
    int stride = (ih.biHeight + 31) / 32 * 4;
    int newSize = stride * ih.biWidth;

    BITMAPFILEHEADER ofh = {0}; ofh.bfType = 0x4D42; ofh.bfSize = 62 + newSize; ofh.bfOffBits = 62;
    BITMAPINFOHEADER oih = {0}; oih.biSize = 40; oih.biWidth = ih.biHeight; oih.biHeight = ih.biWidth; oih.biPlanes = 1; oih.biBitCount = 1; oih.biSizeImage = newSize;

    // 四階段轉換(略,見原始碼)
    // ...

    FILE *of = fopen(out, "wb");
    fwrite(&ofh, sizeof ofh, 1, of);
    fwrite(&oih, sizeof oih, 1, of);
    fwrite(palette, 1, 8, of);
    fwrite(forth, 1, newSize, of);
    fclose(of);
    free(data); /* 釋放所有 malloc 記憶體 */
}

int main() { cw90("original.bmp", "rotated.bmp"); return 0; }

注意事項

  • 僅適用單色圖(biBitCount=1),24/32 位圖需完全不同的像素處理邏輯。
  • LONG 定義:Windows SDK 定義為 long(有號 32 位),原碼 typedef unsigned int LONG 在 64 位 Linux 可能導致 biHeight 讀錯,建議改 typedef long LONG。
  • 記憶體管理:原碼配置多個中間緩衝區(first,second,third,forth,img),僅釋放 img,data,其餘洩漏。實務上應全部 free 或合併緩衝區。
  • 效能:逐 bit 操作極慢,實務可用查表法(256 byte 查表)或 SIMD 加速。

執行結果示意

旋轉前
旋轉後

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