【C言語】Bitmapヘッダ情報を出力するプログラム(構造体、動的領域の確保)

C言語 研修プログラム

ソフトウェア会社の研修時代に作成したプログラムです。
参考になればうれしいです。

今回の研修プログラムはビットマップ形式のファイルからBMPヘッダ情報を読み取って出力するという内容です。

Bitmapファイルのフォーマットについては下記のサイトが詳しく紹介しています。
Bitmapファイルフォーマット

今回の研修プログラムで必要になる知識です。
・構造体のパディング(#pragma packを使用する。)
・fopen、fseek、fcloseを使用してファイルの読み取りとサイズの取得方法
・mallocによる動的領域の確保

スポンサーリンク

Sample Code

/*********************************************************************
bitmap.c:Bitmapファイルヘッダー情報の読み取り

<bitmap.c> ver1.00
-----------------------------------------------------------------------
作成日:
作成者:

***********************************************************************/
//---ヘッダファイル---//
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/************************* マクロ定義 ***********************************/


/************************* データ型 *************************************/

#pragma pack (push, 1)   //パディングを1byteに変更

typedef struct tagBITMAPFILEHEADER {
    unsigned short  bfType;           /* ファイルタイプ */
    unsigned long   bfSize;           /* ファイルサイズ */
    unsigned short  bfReserved1;      /* 予約領域1 */
    unsigned short  bfReserved2;      /* 予約領域2 */
    unsigned long   bfOffBits;        /* 先頭から画像データまでのオフセット */
} BITMAPFILEHEADER;

typedef struct tagBITMAPINFOHEADER {
    unsigned long   biSize;           /* ヘッダサイズ */
    long            biWidth;          /* 画像の幅(px) */
    long            biHeight;         /* 画像の高さ(px) */
    unsigned short  biPlanes;         /* プレーン数 常に1 */
    unsigned short  biBitCount;       /* 1画素あたりのデータサイズ */
    unsigned long   biCompression;    /* 圧縮形式 */
    unsigned long   biSizeImage;      /* 画像データ部のサイズ */
    long            biXPixPerMeter;   /* 横方向解像度(dot/m) */
    long            biYPixPerMeter;   /* 縦方向解像度(dot/m) */
    unsigned long   biClrUsed;        /* 格納されているパレット数(使用色数) */
    unsigned long   biClrImportant;   /* 重要なパレットのインデックス */
} BITMAPINFOHEADER;

typedef struct tagRGBQUAD {
    unsigned char rgbBlue;            /* 青0~255 */
    unsigned char rgbGreen;           /* 緑0~255 */
    unsigned char rgbRed;             /* 赤0~255 */
    unsigned char rgbReserved;        /* 予約領域0 */
} RGBQUAD;

#pragma pack (pop)

/************************** static関数 ********************************/

//---------------------------------------------------------------------
// 関数名 :LoadBitMap
// 機  能 :bitmapファイルを取り込む。
//         bitmapファイルサイズ分の領域をmallocで確保する。
//         BITMAPFILEHEADERとBITMAPINFOHEADERのデータを取り込む。
//         ※確保した領域は呼び出し側で解放すること
// 戻り値 :int* ポインタ(失敗:NULL)
//----------------------------------------------------------------------
BITMAPFILEHEADER *LoadBitMap(    /* 戻り値:BITMAPFILEHEADER* ポインタ*/
   char*  array                  /* i:ファイル名*/
)
{

  long byte_size;

  FILE *fp;
  BITMAPFILEHEADER *pf;
  BITMAPINFOHEADER *pi;
  RGBQUAD          *pr;

  if((fp=fopen(array,"rb")) == NULL){
    printf("%sファイルのオープンに失敗\n", array);
    return NULL;
  }

  printf("%s file open\n", array);

  /* ファイルポインタを末尾に移動*/
  fseek(fp, 0, SEEK_END);

  /* 位置を取得してファイルのバイト数を取得*/
  byte_size = ftell(fp);
  printf("%sファイルのサイズ:%dbyte\n", array, byte_size);

  /* ファイルポインタを先頭に移動*/
  fseek(fp, 0, SEEK_SET);

  /* 動的領域の確保*/
  pf = malloc(byte_size);
  /* フォーマットを変更 */
  /* pfのアドレス領域+1byteからはBITMAPINFOHEADER型にする */
  pi = (BITMAPINFOHEADER*)(pf + 1);
  /* piのアドレス領域+1byteからはRGBQUAD型にする */
  pr = (RGBQUAD*)(pi + 1);

  /* ファイルからBITMAPFILEHEADERサイズだけ読み込む */
  fread(pf, sizeof(BITMAPFILEHEADER), 1, fp);
  /* ファイルからBITMAPINFOHEADERサイズだけ読み込む */
  fread(pi, sizeof(BITMAPINFOHEADER), 1, fp);
  /* ファイルからRGBQUADサイズだけ読み込む */
  fread(pr, sizeof(RGBQUAD), 1, fp);

  if(fclose(fp) == EOF){
    printf("%sファイルを閉じることが出来ませんでした。\n", array);
  }
  else{
    printf("%s file closed\n", array);
  }

  return pf;
}


//----------------------------------------------------------------------
// 関数名 :PrintBitMap
// 機  能 :読み取ったBitmapヘッダ情報を表示
// 戻り値 :void
//-----------------------------------------------------------------------
void PrintBitMap(
  BITMAPFILEHEADER* pf,         /* i:構造体のポインタ*/
  BITMAPINFOHEADER* pi,         /* i:構造体のポインタ*/
  RGBQUAD*          pr          /* i:構造体のポインタ*/
)
{

  printf("\n\t**BITMAPFILEHEADER**\n");
  printf("\tbfType:         %c%c\n",    pf->bfType, (pf->bfType >> 8));
  printf("\tbfSize:         %dbyte\n",  pf->bfSize);
  printf("\tbfReserved1:    %d\n",      pf->bfReserved1);
  printf("\tbfReserved2:    %d\n",      pf->bfReserved2);
  printf("\tbfOffBits:      %dbyte\n",  pf->bfOffBits);


  printf("\n\t**BITMAPINFOHEADER**\n");
  printf("\tbiSize:         %dbyte\n",  pi->biSize);
  printf("\tbiWidth:        %dpx\n",    pi->biWidth);
  printf("\tbiHeight:       %dpx\n",    pi->biHeight);
  printf("\tbiPlanes:       %d\n",      pi->biPlanes);
  printf("\tbiBitCount:     %dbit\n",   pi->biBitCount);
  printf("\tbiCompression:  %d\n",      pi->biCompression);
  printf("\tbiSizeImage:    %dbyte\n",  pi->biSizeImage);
  printf("\tbiXPixPerMeter: %ddot/m\n", pi->biXPixPerMeter);
  printf("\tbiYPixPerMeter: %ddot/m\n", pi->biYPixPerMeter);
  printf("\tbiClrUsed:      %d\n",      pi->biClrUsed);
  printf("\tbiClrImportant: %d\n",      pi->biClrImportant);


  printf("\n\t**RGBQUAD**\n");
  printf("\r\tgbBlue:       %d\n",      pr->rgbBlue);
  printf("\r\tgbGreen:      %d\n",      pr->rgbGreen);
  printf("\r\tgbRed:        %d\n",      pr->rgbRed);
  printf("\r\tgbReserved:   %d\n",      pr->rgbReserved);

}


/***********************************************************************
---main関数---
************************************************************************/
int main(int argc, char** argv)
{

  BITMAPFILEHEADER *pfh;
  BITMAPINFOHEADER *pih;
  RGBQUAD          *prgb;

  /* Bitmapファイルヘッダ情報の読み取り(pfhは解放必要) */
  pfh = LoadBitMap(argv[1]);
  pih = (BITMAPINFOHEADER*)(pfh + 1);  //キャストしてフォーマット変更
  prgb = (RGBQUAD*)(pih + 1);          //キャストしてフォーマット変更

  if(pfh == NULL){
    printf("エラーが発生しました。\n");
    return -1;
  }

  printf("%c%c\n", pfh->bfType, (pfh->bfType >> 8));

  /* 読み取ったファイルがBMP形式かどうか判定 */
  if(pfh->bfType != 0x4D42){
    printf("ビットマップではありません。\n");
  }
  else{
    printf("ビットマップです。\n");
    PrintBitMap(pfh, pih, prgb);  //BMPヘッダ情報を表示する
  }

  /* 確保した領域を解放 */
  free(pfh);

  return 0;
}

実行例

今回はこのBMPファイルをコマンドライン引数で指定します。

こんな感じでBitmapファイルフォーマットを表示することが出来ました!

その他:研修で作成したC言語プログラム

その他のC言語プログラムはこの投稿にまとめてあります!

C言語の初心者用のコードなので是非活用して下さい。
【C言語】研修 サンプルプログラム集

コメント

タイトルとURLをコピーしました