参考資料 1A
2010/05/01

BMPファイルの構成


ビットマップファイルに記録されている画像の配置に関する情報

BMPファイルは、以下の構造を持っている(Windows形式のみ)
背景が水色の部分は、BMPファイルのヘッダー部、背景が黄色の部分は、画像データ部を表す
ファイルヘッダー部
typedef struct tagBITMAPFILEHEADER {
  WORD  bfType;     // unsigned short 2byte "BM"  0x4D42
  DWORD bfSize;     // unsigned long  4byte ファイル全体の大きさ[byte]
  WORD  bfReserved1;// unsigned short 2byte 0 Fixed
  WORD  bfReserved2;// unsigned short 2byte 0 Fixed
  DWORD bfOffBits;  // unsigned long  4byte ファイルの先頭から
                    //                      画像データまでのオフセット
} BITMAPFILEHEADER,*LPBITMAPFILEHEADER,*PBITMAPFILEHEADER;
ファイルヘッダー部
typedef struct tagBITMAPINFOHEADER{
  DWORD biSize;         // unsigned long  4byte 40 sizeof(BITMAPINFOHEADER)
  LONG  biWidth;        // long           4byte 画像の幅
  LONG  biHeight;       // long           4byte 画像の高さ±で画像の配置が逆
  WORD  biPlanes;       // unsigned short 2byte 1 Fixed
  WORD  biBitCount;     // unsigned short 2byte 1画素あたりの色を表現するビット数
  DWORD biCompression;  // unsigned long  4byte 画像データの圧縮形式 0, 1, 2, 3
                        //                      0: BI_RGB(無圧縮)
  DWORD biSizeImage;    // unsigned long  4byte 画像データのバイト数
  LONG  biXPelsPerMeter;// long           4byte H 解像度 
  LONG  biYPelsPerMeter;// long           4byte V 解像度 
  DWORD biClrUsed;      // unsigned long  4byte 格納パレット数[使用色数]
  DWORD biClrImportant; // unsigned long  4byte 重要色数 0[全て重要] or
n≦
                        //                      biClrUsed 先頭からnは重要な色
} BITMAPINFOHEADER,*LPBITMAPINFOHEADER,*PBITMAPINFOHEADER;
カラーマップ部 (BITMAPINFOHEADER->biBitCount が24|32 の場合は存在しない)
typedef struct tagRGBQUAD {
  BYTE  rgbBlue;
    // unsigned char
  BYTE  rgbGreen;    // unsigned char
  BYTE  rgbRed;      // unsigned char
  BYTE  rgbReserved; // unsigned char
} RGBQUAD,*LPRGBQUAD;
画像データ部
 
画像の横一列分のデータ(左から右方向)を単位にファイルに記録されている
BITMAPINFOHEADER->biHeight の値が、正か負かでデータの格納順序が逆転する事に注意 
BITMAPINFOHEADER->biHeight が正の値の場合は、画像の最下部のデータから順に画像の
上部に向かって記録され、負の場合は、画像の上部のデータから、画像の最下部に向かって、
情報がファイルに記録されている事を考慮する必要がある。 (Win32APIで提供される関数は、
Y方向の大きさをマイナスで記録されている画像をロード出来ない場合あり、注意する事。)

その他
 画像データは、横一列分のデータが、4の整数倍に調整されているので注意する事。

 1行につき最大で3バイトのデータがパディングされている。
 BITMAPINFOHEADER->biBitCount が、 8|24 の場合は、以下の計算で1行分のバイト数が判る
 BytePerline = (bmpIH.biWidth * (bmpIH.biBitCount >> 3) +3) & ~3 ;
  PaddingByte = BytePerline - bmpIH.biWidth * (bmpIH.biBitCount >> 3) ;
 32ビットカラー画像の場合は、必ず4バイト境界に配置されるので、パディングは存在しない。
 
ファイル全体のバイト数も4の整数倍にする??? 2バイトのデータが加えられている場合がある
32ビット形式のBMPファイルは、データサイズは大きくなってしまうが、32ビットCPUで非常に扱い易い
形式なので、このフォーマットを流用して使用する事は、使用者に負担をかけない優れた方法である

具体例による構造の確認

32ビットカラーの5x5 画素で構成されている画像の例
グレー部の値は、(A,R,G,B) = (0x00,0x80,0x80,0x80)
白い部分の値は、(A,R,G,B) = (0x00,0xFF,0xFF,0xFF)


  Y軸を正の値とする形式(5x5.bmp) と Y軸を負の値とする形式(5x5R.bmp) で画像をファイルに保存する。
  画像表示ツールで表示すれば、どちらもファイルも画面上では同じに表示される。(されなければならない)


5x5.bmp のヘッダー情報
-- BITMAPFILEHEADER -- (14 Byte)
  unsigned short 2byte  "BM"     bfType        = 0x4D42
  unsigned long  4byte  ※1     bfSize        = 156  (0x0000009C)
  unsigned short 2byte  0 Fixed  bfReserved1   = 0    (0x0000)
  unsigned short 2byte  0 Fixed  bfReserved2   = 0    (0x0000)
  unsigned long  4byte  ※2     bfOffBits     = 54   (0x00000036)
-- BITMAPINFOHEADER -- (40 Byte)
  unsigned long  4byte  40 byte  biSize          = 40 (0x00000028)
  long           4byte  画像の幅 biWidth         = 5  (0x00000005)
  long     ※3  4byte  画像の高 biHeight        = 5  (0x00000005)
  unsigned short 2byte  1 Fixed  biPlanes        = 1  (0x0001)
  unsigned short 2byte  ※4     biBitCount      = 32 (0x0020)
  unsigned long  4byte  ※5     biCompression   = 0  (0x00000000)
  unsigned long  4byte  ※6     biSizeImage     = 102  (0x00000066)
  long           4byte H解像度   biXPelsPerMeter = 2834 (0x00000B12)
  long           4byte V解像度   biYPelsPerMeter = 2834 (0x00000B12)
  unsigned long  4byte  ※7     biClrUsed       = 0  (0x00000000)
  unsigned long  4byte 重要色数  biClrImportant  = 0  (0x00000000)

5x5.bmpのファイルのダンプ情報
5x5 standard
赤枠で囲まれた部分が、実際の画像データ部
画像の最下部の行から、1行単位で、画像の最上部の行までの画像データが、
ファイルの先頭に書かれたヘッダー部に続き、順に格納されている。




5x5R.bmp の ヘッダー情報
-- BITMAPFILEHEADER -- (14 Byte)
  unsigned short 2byte  "BM"     bfType        = 0x4D42
  unsigned long  4byte  ※1     bfSize        = 156  (0x0000009C)
  unsigned short 2byte  0 Fixed  bfReserved1   = 0    (0x0000)
  unsigned short 2byte  0 Fixed  bfReserved2   = 0    (0x0000)
  unsigned long  4byte  ※2     bfOffBits     = 54   (0x00000036)
-- BITMAPINFOHEADER -- (40 Byte)
  unsigned long  4byte  40 byte  biSize          = 40 (0x00000028)
  long           4byte  画像の幅 biWidth         = 5  (0x00000005)
  long     ※3  4byte  画像の高 biHeight        = -5 (0xFFFFFFFB)
  unsigned short 2byte  1 Fixed  biPlanes        = 1  (0x0001)
  unsigned short 2byte  ※4     biBitCount      = 32 (0x0020)
  unsigned long  4byte  ※5     biCompression   = 0  (0x00000000)
  unsigned long  4byte  ※6     biSizeImage     = 102  (0x00000066)
  long           4byte H解像度   biXPelsPerMeter = 2834 (0x00000B12)
  long           4byte V解像度   biYPelsPerMeter = 2834 (0x00000B12)
  unsigned long  4byte  ※7     biClrUsed       = 0  (0x00000000)
  unsigned long  4byte 重要色数  biClrImportant  = 0  (0x00000000)


5x5R.bmpのファイルのダンプ情報
5x5 inversion
赤枠で囲まれた部分が、実際の画像データ部
画像の最上部の行から、1行単位で、画像の最下部の行までの画像データが、
ファイルの先頭に書かれたヘッダー部に続き、順に格納されている。(画像左最上部
の画素の値(B,G,R,A)=(0x80,0x80,0x80,0x00)がファイルのヘッダー部に続いている)



画像データの画素に対するBMPのファイル内の並び情報
5x5 inversion
赤枠で囲まれた部分が、実際の画像のデータ部である。Y軸の符号により指示された方向で
行を単位に横方向の画素分のデータ(4バイト*横方向の画素数)が記録されている。
(この例では、32ビット形式なのでデータは必ず4バイト境界になり、パディングの必要は無い)
32ビット形式では、1画素の値 B,G,R,A(A:未使用の予約部)は、各1バイトからなる4要素で
構成され、かつ、B、G、R、Aの順でファイルに記録されている


  1画素を構成するビット数が、8、24、32ビットで画像データを圧縮しないBMPファイルをコンピュータの
  メモリーに読み込み、コンピュータのディスプレイに表示させる場合のアドレス計算について記述する。
  コンピュータの画像格納用場所の最初のアドレスを、imageBaseAdder とし、画像の横方向の大きさを LX、
  画像の横方向の大きさを LY、1画素を構成するバイト数を n、とし、対象の画素の座標を(x,y)とする。
  コンピュータの画像データ格納用メモリへアクセスする時の座標系は、表示画像の左下を原点とする系で、
  Windowsのグラフィック処理で使用している左上を原点とする系と逆になっているので注意が必要。

  ステップ1、横1行分で使用するデータの大きさを算出する。(4バイト境界に調整する処理を含む)
        BytePerLine = lx * n + 4バイト境界に調整バイト数(0,1,2,3)
BytePerLine = ((LX * n +3) / LX ) * LX
LX * n +3 4バイト境界にするための切り上げ処理
(LX * n +3) / LX 4バイト境界に調整する必要がある場合 LX+1 になる
4バイト境界で調整処理が不要な場合  LX  になる
((LX * n +3) / LX ) * LX 1行分のバイト数が求まる(最適化処理させない事)

  ステップ2、画像データが画像の上部~下部に向かって格納されているか、下部~上部に向かっているか
        判断し、適切な納用場所の最初のアドレスを算出する
        ThisY = LY > 0 ? y : ( (LY-1) - y ) ;    (LY-1) は、左上の Y 座標

  ステップ3、目標の座標 = imageBaseAdder[Y][X] ;
               imageBaseAdder + (横1行分のバイト数 × Yの座標) + (Xの座標) * 1画素分のバイト数
               imageBaseAdder + ( BytePerLine * ThisY ) + ThisX * n

   TargetPixelAddress = (char *)imageBaseAdder + (BytePerLine * ThisY) + ThisX * n ;

     基準点のアドレスを、char * 又は、unsigned char * (1移動量が1バイト)宣言をする事


  Ex. 色要素(画素)のデータを読み出す記述方法
   Y = *(unsigned char *)TargetPixelAddress ; // index data
               //   R = ColorMap[Y].rgbRed, G = ColorMap[Y].rgbGreen, B = ColorMap[Y].rgbBlue
   B = *( (unsigned char *)TargetPixelAddress +0 ) ; // 24 or 32
   G = *( (unsigned char *)TargetPixelAddress +1 ) ; // 24 or 32
   R = *( (unsigned char *)TargetPixelAddress +2 ) ; // 24 or 32
   A = *( (unsigned char *)TargetPixelAddress +3 ) ; // 32




go to TopPage go to CategoryTop