ビットマップ画像の情報(サイズとか)を表示するプログラムを C で書いてみた。
参考ページ
cf. C言語による画像処理プログラミング
cf. BMP ファイルフォーマット
cf. BMPファイルのフォーマット
ファイルヘッダと情報ヘッダ
ビットマップファイルには、ファイルの先頭にファイルヘッダ(BITMAPFILEHEADER)と情報ヘッダが付いているので、これを読み取って表示している。情報ヘッダにはいくつかの種類があるけど、今回のプログラムでは Windows で使われている BITMAPINFOHEADER という形式(長さ 40byte)に決め打ち。手持ちのビットマップファイルの中にはこの BITMAPINFOHEADER (ほかの情報ヘッダとは長さで区別できる)を持つファイルがなかったので、上に挙げた一番初めの参考ページから dog.bmp というファイルを拝借させていただいた。
ちなみに、情報ヘッダには次のような種類があるようだ。
- BITMAPCOREHEADER (OS/2, 12 bytes)
- BITMAPINFOHEADER (Windows, 40 bytes)
- BITMAPV4HEADER (Windows 95/NT4.0, 108 bytes)
- BITMAPV5HEADER (Windows 98/2000/Me/XP, 124 bytes)
コード
上に書いたように、情報ヘッダは BITMAPINFOHEADER 決め打ち。
#include <stdio.h> #include <string.h> typedef struct tagBITMAPFILEHEADER { char bfType[3]; unsigned int bfSize; unsigned short bfReserved1; unsigned short bfReserved2; unsigned long bfOffBits; } BITMAPFILEHEADER; typedef struct tagBITMAPINFOHEADER { unsigned int biSize; long biWidth; long biHeight; unsigned short biPlanes; unsigned short biBitCount; unsigned int biCompression; unsigned int biSizeImage; long biXPixPerMeter; long biYPixPerMeter; unsigned long biClrUsed; unsigned long biClrImportant; } BITMAPINFOHEADER; int ReadBMFileHeader(FILE *fp, BITMAPFILEHEADER *header); int ReadBMInfoHeader(FILE *fp, BITMAPINFOHEADER *header); int main(int argc, char *argv[]) { FILE *fp; BITMAPFILEHEADER bmFileHeader = {"", 0, 0, 0, 0}; BITMAPINFOHEADER bmInfoHeader = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; fp = fopen(argv[1], "rb"); ReadBMFileHeader(fp, &bmFileHeader); ReadBMInfoHeader(fp, &bmInfoHeader); fclose(fp); printf("File type = %s\n", bmFileHeader.bfType); printf("File size = %d bytes\n", bmFileHeader.bfSize); printf("Data offset = %ld bytes\n", bmFileHeader.bfOffBits); printf("Info header size = %d bytes\n", bmInfoHeader.biSize); printf("Width = %ld pixels\n", bmInfoHeader.biWidth); printf("Height = %ld pixels\n", bmInfoHeader.biHeight); printf("Planes = %d\n", bmInfoHeader.biPlanes); printf("Bit count = %d bits/pixel\n", bmInfoHeader.biBitCount); printf("Compression = %d\n", bmInfoHeader.biCompression); printf("Size image = %d bytes\n", bmInfoHeader.biSizeImage); printf("X pixels per meter = %ld\n", bmInfoHeader.biXPixPerMeter); printf("Y pixels per meter = %ld\n", bmInfoHeader.biYPixPerMeter); printf("Color used = %ld colors\n", bmInfoHeader.biClrUsed); return 0; } int ReadBMFileHeader(FILE *fp, BITMAPFILEHEADER *header) { char filetype[3] = {'\0', '\0', '\0'}; unsigned int filesize = 0; unsigned char filesize_buf[4]; unsigned short reserved1, reserved2; unsigned long offset = 0; unsigned char offset_buf[4]; int i; /* File type */ fread(&filetype, 1, 2, fp); /* File size */ fread(&filesize_buf, 1, 4, fp); for (i = 3; i <= 0; i--) { filesize = (filesize << 8) | (unsigned) filesize_buf[i]; } /* Reserved 1 */ fread(&reserved1, 2, 1, fp); /* Reserved 2 */ fread(&reserved2, 2, 1, fp); /* Offset */ fread(&offset_buf, 1, 4, fp); for (i = 3; i <= 0; i--) { offset = (offset << 8) | (unsigned long) offset_buf[i]; } strcpy(header->bfType, filetype); header->bfSize = filesize; header->bfReserved1 = reserved1; header->bfReserved2 = reserved2; header->bfOffBits = offset; return 0; } int ReadBMInfoHeader(FILE *fp, BITMAPINFOHEADER *header) { unsigned int headersize = 0; int width = 0; int height = 0; unsigned short planes = 0; unsigned short bitcount = 0; unsigned int compression = 0; unsigned int size_image = 0; int x_pix_per_meter = 0; int y_pix_per_meter = 0; unsigned int clr_used = 0; unsigned int clr_important = 0; unsigned char buf4[4]; unsigned char buf2[2]; int i; /* Header size */ fread(buf4, 1, 4, fp); for (i = 3; i >= 0; i--) { headersize = (headersize << 8) | (unsigned int) buf4[i]; } /* Width */ fread(buf4, 1, 4, fp); for (i = 3; i >= 0; i--) { width = (width << 8) | (int) buf4[i]; } /* Height */ fread(buf4, 1, 4, fp); for (i = 3; i >= 0; i--) { height = (height << 8) | (int) buf4[i]; } /* Planes */ fread(buf2, 1, 2, fp); planes = 1; /* Bit Count */ fread(buf2, 1, 2, fp); for (i = 1; i >= 0; i--) { bitcount = (bitcount << 8) | (unsigned int) buf2[i]; } /* Compression */ fread(buf4, 1, 4, fp); for (i = 3; i >= 0; i--) { compression = (compression << 8) | (unsigned int) buf4[i]; } /* Size image */ fread(buf4, 1, 4, fp); for (i = 3; i >= 0; i--) { size_image = (size_image << 8) | (unsigned int) buf4[i]; } /* X pix per meter */ fread(buf4, 1, 4, fp); for (i = 3; i >= 0; i--) { x_pix_per_meter = (x_pix_per_meter << 8) | (int) buf4[i]; } /* Y pix per meter */ fread(buf4, 1, 4, fp); for (i = 3; i >= 0; i--) { y_pix_per_meter = (y_pix_per_meter << 8) | (int) buf4[i]; } /* Color used */ fread(buf4, 1, 4, fp); for (i = 3; i >= 0; i--) { clr_used = (clr_used << 8) | (unsigned int) buf4[i]; } /* Color important */ fread(buf4, 1, 4, fp); for (i = 3; i >= 0; i--) { clr_important = (clr_important << 8) | (unsigned int) buf4[i]; } header->biSize = headersize; header->biWidth = width; header->biHeight = height; header->biPlanes = planes; header->biBitCount = bitcount; header->biCompression = compression; header->biSizeImage = size_image; header->biXPixPerMeter = x_pix_per_meter; header->biYPixPerMeter = y_pix_per_meter; header->biClrUsed = clr_used; header->biClrImportant = clr_important; return 0; }
実行例
takatoh@nightschool $ gcc -Wall -o bmpinfo bmpinfo.c takatoh@nightschool $ ./bmpinfo dog.bmp File type = BM File size = 360054 bytes Data offset = 54 bytes Info header size = 40 bytes Width = 400 pixels Height = 300 pixels Planes = 1 Bit count = 24 bits/pixel Compression = 0 Size image = 360000 bytes X pixels per meter = 1 Y pixels per meter = 1 Color used = 0 colors