BMP 檔的載入、處理與儲存

高等 C 語言

簡介

字串

指標與陣列

函數

結構

物件導向

記憶體

檔案

錯誤處理

巨集處理

C 與組合語言

資料結構

動態字串

動態陣列

鏈結串列

雜湊表

開發環境

Make

Cygwin

MinGW

DevC++

wxDevC++

編譯器

gcc 編譯器

TinyCC 編譯器

LCC 編譯器

應用主題

CGI 程式

GNU 程式

視窗程式

影像處理

練習題

訊息

相關網站

參考文獻

最新修改

簡體版

English

執行結果

D:\ccc101\cp\bmp>gcc bmp.c -o bmp

D:\ccc101\cp\bmp>bmp ccc.bmp ccc1.bmp
==== Header ====
Signature = 4D42
FileSize = 59058
DataOffset = 54
==== Info ======
size = 40
Width = 132
Height = 149
Planes = 1
BitsPerPixel = 24
Compression = 0
ImageSize = 0
XpixelsPerM = 3780
YpixelsPerM = 3780
ColorsUsed = 0
ColorsImportant = 0
輸入檔 輸出檔
ccc.bmp ccc1.bmp

程式碼

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

typedef long UINT32;
typedef unsigned short int UINT16;
typedef unsigned char BYTE;

#define HEADER_SIZE 14
#define INFO_SIZE 40
#define DataSize(bmp) (bmp->width*bmp->height*3)

typedef struct BMP {
    BYTE header[HEADER_SIZE];    
    BYTE info[INFO_SIZE];
    // Header
    UINT16 signature; // Magic Number = "BM" = 0x4D42
    UINT32 fileSize; // File size in bytes
    UINT32 hreserved; // unused (=0)
    UINT32 dataOffset; // File offset to Raster Data
    // InfoHeader
    UINT32 size; // Size of InfoHeader =40 
    UINT32 width; // Bitmap Width
    UINT16 height; // Bitmap Height
    UINT16 planes; // Number of Planes (=1)
    UINT16 bitsPerPixel; // Bits per Pixel, 1, 4, 8, 16, 24
    UINT32 compression; // Type of Compression, 0 = BI_RGB no compression, 1 = BI_RLE8 8bit RLE encoding, 2 = BI_RLE4 4bit RLE encoding
    UINT32 imageSize; // (compressed) Size of Image, It is valid to set this =0 if Compression = 0
    UINT32 xPixelsPerM; // horizontal resolution: Pixels/meter
    UINT32 yPixelsPerM; // vertical resolution: Pixels/meter
    UINT32 colorsUsed; // Number of actually used colors
    UINT32 colorsImportant; // Number of important colors , 0 = all
    // ColorTable : present only if Info.BitsPerPixel <= 8 colors should be ordered by importance
    BYTE blue; // Blue intensity
    BYTE green; // Green intensity
    BYTE red; // Red intensity
    BYTE creserved; // unused (=0)
    // Raster Data
    BYTE *data;
} BMP;

typedef struct Pixel {
    BYTE R;
    BYTE G;
    BYTE B;
} Pixel;

#define U16(x)    ((unsigned short) (x))
#define U32(x)    ((int) (x))
#define B2U16(bytes,offset)  (U16(bytes[offset]) | U16(bytes[offset+1]) << 8)
#define B2U32(bytes,offset)  (U32(bytes[offset]) | U32(bytes[offset+1]) << 8 | \
                   U32(bytes[offset+2]) << 16 | U32(bytes[offset+3]) << 24)

int bmpLoad(BMP *bmp, char *fileName) {
   FILE *file;
   BYTE header[14];
   BYTE info[40];

   if ((file = fopen(fileName, "rb") ) == NULL ) {
      fprintf(stderr, "Error: bmpLoad(), File open fail!\n");
      exit(0);
   }

   fread(header, 1, HEADER_SIZE, file);
   fread(info, 1, INFO_SIZE, file);
   memcpy(bmp->header, header, HEADER_SIZE);
   memcpy(bmp->info, info, INFO_SIZE);
   // Header
   bmp->signature = B2U16(header,0); assert(bmp->signature == 0x4D42);
   bmp->fileSize = B2U32(header,2);
   bmp->dataOffset = B2U32(header,10);
   // InfoHeader
   bmp->size = B2U32(info,0); assert(bmp->size==40);
   bmp->width = B2U32(info,4);
   bmp->height = B2U32(info,8);
   bmp->planes = B2U16(info,12); assert(bmp->planes==1);
   bmp->bitsPerPixel = B2U16(info,14); assert(bmp->bitsPerPixel==24);
   bmp->compression = B2U32(info,16);
   bmp->imageSize = B2U32(info,20);
   bmp->xPixelsPerM = B2U32(info,24);
   bmp->yPixelsPerM = B2U32(info,28);
   bmp->colorsUsed = B2U32(info,32);
   bmp->colorsImportant = B2U32(info,36);

   bmp->data = malloc(DataSize(bmp));
   fseek(file, bmp->dataOffset, SEEK_SET);
   fread(bmp->data, 1, DataSize(bmp), file);

   fclose (file);
}

int bmpPrint(BMP *bmp) {
   printf("==== Header ====\n");
   printf("Signature = %04X\n", bmp->signature); // 0x4d42 = BM
   printf("FileSize = %ld \n", bmp->fileSize);
   printf("DataOffset = %ld \n", bmp->dataOffset);
   printf("==== Info ======\n");
   printf("size = %ld \n", bmp->size);
   printf("Width = %ld \n", bmp->width);
   printf("Height = %ld \n", bmp->height);
   printf("Planes = %d \n", bmp->planes);
   printf("BitsPerPixel = %d \n", bmp->bitsPerPixel);
   printf("Compression = %ld \n", bmp->compression);
   printf("ImageSize = %ld \n", bmp->imageSize);
   printf("XpixelsPerM = %ld \n", bmp->xPixelsPerM);
   printf("YpixelsPerM = %ld \n", bmp->yPixelsPerM);
   printf("ColorsUsed = %ld \n", bmp->colorsUsed);
   printf("ColorsImportant = %ld \n", bmp->colorsImportant);
}

int bmpSetPixel(BMP *bmp, int x, int y, BYTE R, BYTE G, BYTE B) {
    Pixel *pixel;
    int idx = y * bmp->width + x;
    pixel = (Pixel*) &bmp->data[idx * sizeof(Pixel)];
    pixel->R = R;
    pixel->G = G;
    pixel->B = B;
}

int bmpSetBox(BMP *bmp, int x, int y, int w, int h, BYTE R, BYTE G, BYTE B) {
    int i,j;
    for (i=0; i< 0+w; i++)
        for (j=0; j<h; j++)
            bmpSetPixel(bmp, x+i, y+j, R, G, B);
}

int bmpSave(BMP *bmp, char *fileName) {
    FILE *file;
    if ((file = fopen(fileName, "wb") ) == NULL ) {
        fprintf(stderr, "Error: bmpSave(), File create fail!\n");
        exit(0);
    }
    fwrite(bmp->header, 1, HEADER_SIZE, file);
    fwrite(bmp->info, 1, INFO_SIZE, file);
    fseek(file, bmp->dataOffset, SEEK_SET);
    fwrite(bmp->data, 1, DataSize(bmp), file);
    fclose(file);
}

int main(int argc, char *argv[]) {
    BMP bmp;
    bmpLoad(&bmp, argv[1]);
    bmpPrint(&bmp);
    bmpSetBox(&bmp, 0, 0, 20, 20, 0x66, 0x33, 0x99);
    bmpSave(&bmp, argv[2]);
    return 0;
}

參考文獻

  1. BMP image format, Written by Paul Bourke, July 1998 (讚!)
  2. C/displaying a bitmap in console programme
  3. http://www.daubnet.com/en/file-format-bmp#RasterData
  4. Learning By Explain & Example BMP FILE

Facebook

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License