bfType='BM'、檔案大小、資料偏移量。biBitCount)、壓縮方式、影像大小等。stride = (width+31)/32*4)。原圖 W×H,旋轉後變 H×W。單色圖每像素 1 bit,需逐 bit 讀取、重新排列、打包寫入。本程式分四階段:
first[H×W],每元素 0/1。second[new_row][new_col] = first[old_row][old_col],對應 second[i][j] = first[W-1-j][i]。third 補 0。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; }
long(有號 32 位),原碼 typedef unsigned int LONG 在 64 位 Linux 可能導致 biHeight 讀錯,建議改 typedef long LONG。first,second,third,forth,img),僅釋放 img,data,其餘洩漏。實務上應全部 free 或合併緩衝區。
