| ファイルヘッダ | BITMAPFILEHEADER (14byte) |
| 情報ヘッダ | BITMAPINFOHEADER (Windows) または BITMAPCOREHEADER (OS/2) + カラーパレット(無い場合もある) |
| 画像データ |
最初に 14 byte 固定のファイルヘッダ部分があります。最初の 2 byte が 'BM' かどうかで,ビットマップファイルを識別します。
typedef struct tagBITMAPFILEHEADER {
unsigned short bfType;
unsigned long bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned long bfOffBits;
} BITMAPFILEHEADER
| bfType | 2 byte | ファイルタイプ | 'BM' - OS/2, Windows Bitmap |
| bfSize | 4 byte | ファイルサイズ (byte) | |
| bfReserved1 | 2 byte | 予約領域 | 常に 0 |
| bfReserved2 | 2 byte | 予約領域 | 常に 0 |
| bfOffBits | 4 byte | ファイル先頭から画像データまでのオフセット (byte) |
情報ヘッダには何種類かあります。
情報ヘッダの最初の 4 Byte に情報ヘッダ部のサイズなので,この値で種類を区別します。
'12' ならば [BITMAPCOREHEADER] (OS/2),'40' ならば [BITMAPINFOHEADER] (Windows) になります。
他にも,Windows NT 4.0 以降で使用可能な "BITMAPV4HEADER" やWindows 98/2000 以降で使用可能な "BITMAPV5HEAER" があるようです。
| 12 byte | BITMAPCOREHEADER | OS/2 bitmap |
| 40 byte | BITMAPINFOHEADER | Windows Bitmap |
画像の高さは符号付きの値で,正数ならばボトムアップ(左下から右上),負数ならばトップダウン(左上から右下)の順に,データが記録されています。
標準は正数でボトムアップです。
OS/2 Bitmap の情報ヘッダは以下のようになります。
typedef struct tagBITMAPCOREHEADER{
unsigned long bcSize;
short bcWidth;
short bcHeight;
unsigned short bcPlanes;
unsigned short bcBitCount;
} BITMAPCOREHEADER;
| bcSize | 4 byte | 情報ヘッダのサイズ (byte) | 12 |
| bcWidth | 2 byte | 画像の幅 (ピクセル) | |
| bcHeight | 2 byte | 画像の高さ (ピクセル) | bcHeight の値が正数なら,画像データは下から上へ bcHeight の値が負数なら,画像データは上から下へ |
| bcPlanes | 2 byte | プレーン数 | 常に 1 |
| bcBitCount | 2 byte | 1画素あたりのデータサイズ (bit) | 1 - 2 色ビットマップ 4 - 16 色ビットマップ 8 - 256 色ビットマップ (16 - 65536色(high color)ビットマップ 正式に対応していない) 24 - 1677万色(true color)ビットマップ 32 - 1677万色(true color)ビットマップ |
Windows bitmap の情報ヘッダは以下のようになります。
最初の5項目については,OS/2 ヘッダ (BITMAPCOREHEADER) と同じ情報です(ただし,画像の幅,高さについては大きさが違います)。
typedef struct tagBITMAPINFOHEADER{
unsigned long biSize;
long biWidth;
long biHeight;
unsigned short biPlanes;
unsigned short biBitCount;
unsigned long biCompression;
unsigned long biSizeImage;
long biXPixPerMeter;
long biYPixPerMeter;
unsigned long biClrUsed;
unsigned long biClrImporant;
} BITMAPINFOHEADER;
| biSize | 4 byte | 情報ヘッダのサイズ (byte) | 40 |
| biWidth | 4 byte | 画像の幅 (ピクセル) | |
| biHeight | 4 byte | 画像の高さ (ピクセル) | biHeight の値が正数なら,画像データは下から上へ biHeight の値が負数なら,画像データは上から下へ |
| biPlanes | 2 byte | プレーン数 | 常に 1 |
| biBitCount | 2 byte | 1 画素あたりのデータサイズ (bit) | 1 - 2 色ビットマップ 4 - 16 色ビットマップ 8 - 256 色ビットマップ (16 - 65536色(high color)ビットマップ 正式に対応していない) 24 - 1677万色(true color)ビットマップ 32 - 1677万色(true color)ビットマップ |
| biCopmression | 4 byte | 圧縮形式 | 0 - BI_RGB (無圧縮) 1 - BI_RLE8 (RunLength 8 bits/pixel) 2 - BI_RLE4 (RunLength 4 bits/pixel) 3 - Bitfields |
| biSizeImage | 4 byte | 画像データ部のサイズ (byte) | 96dpi ならば3780 0 の場合もある |
| biXPixPerMeter | 4 byte | 横方向解像度 (1mあたりの画素数) | 96dpi ならば3780 0 の場合もある |
| biYPixPerMeter | 4 byte | 縦方向解像度 (1mあたりの画素数) | 96dpi ならば3780 0 の場合もある |
| biClrUsed | 4 byte | 格納されているパレット数 (使用色数) | 0 の場合もある |
| biCirImportant | 4 byte | 重要なパレットのインデックス | 0 の場合もある |
圧縮形式 biCompression 以下の値は 0 の場合もあり,その場合にはデフォルト値が使われます。
圧縮形式 biCompression が 0 ではない場合,画像は圧縮されています。
になっています。
圧縮形式 biCompresson = 3 のビットフィールドの場合は,BITMAPINFOHEADER 直後に
RGB の順に 4 * 3 byte (12byte) のビットフィールドマスクがあり,この内容でデータ形式が決まります。
圧縮形式 biCompression が 0 以外の値の場合には,画像のサイズ biSizeImage を 0 にすることはできません。
biBitCount が 1, 4, 8 の場合には,BiClrUsed に実際に使用されているカラーパレットの色数が記録されています。0 の場合には,biBitCount と同じとみなされます。
となります。
計算式で書くと "biClrUsed = 1 << biBitCount" となります。
struct BitField {
unsigned short value1:4;
unsigned short value2:4;
};
構造体メンバの宣言で ":" をつけて,必要なビット数を書きます。BitCount の値が 1, 4, 8 の場合に存在します。
で1つの色を表現しています。
BitCount が 1, 4, 8 の場合には,画像データにカラーパレットの色番号が記録されていて,色番号が指し示すカラーパレットの色が表示されます。
BitCount が 24, 32 の場合には,画像データに直接色データが記録されています。
typedef struct tagRGBTRIPLE{
unsigned char rgbBlue;
unsigned char rgbGreen;
unsigned char rgbRed;
} RGBTRIPLE;
| rgbBlue | 青 | 0 〜 255 |
| rgbGreen | 緑 | 0 〜 255 |
| rgbRed | 赤 | 0 〜 255 |
typedef struct tagRGBQUAD{
unsigned char rgbBlue;
unsigned char rgbGreen;
unsigned char rgbRed;
unsigned char rgbReserved;
} RGBQUAD;
| rgbBlue | 青 | 0 〜 255 |
| rgbGreen | 緑 | 0 〜 255 |
| rgbRed | 赤 | 0 〜 255 |
| rgbReserved | 予約領域 | 0 |
( 0,99) (99,99) (100,99) ↑---------->| 0 | ↑---------->| 0 | ↑---------->| 0 | ↑---------->| 0 | ↑---------->| 0 | ( 0, 0) (99, 0) (100, 0)
line = (Width * BitCount) / 8; // 1 ラインあたりのデータ数
if ((line % 4) != 0) {
line = ((line / 4) + 1) * 4; // 4byte 境界にあわせる
}
for(i = 0; i < Height; i++) {
position = OffBits + line * (Height - (i + 1)); // 行の先頭位置
fseek(fp, position, SEEK_SET);
fread(buf, line, 1, fp); // 値の読み込み
}
| RED | GREEN | BLUE | ||
![]() |
→ | ![]() |
![]() |
![]() |
![]() |
→ | ![]() |