ソフトウェア会社の研修時代に作成したプログラムです。
参考になればうれしいです。
今回の研修プログラムはビットマップ形式のファイルから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言語】研修 サンプルプログラム集
コメント