投稿者 tel | 2010年8月13日

画像処理プログラミング – Bitmapの読み込み

前回は画像クラスを作ったので次は画像の読み込み処理を作る。画像の形式はいろいろ存在するが内部構造が簡単なBitmapを読み込む関数を作る。Bitmapの形式については探せば山ほど出てくるので特に書かない。以下コード。

#pragma pack(1)

struct BitmapFileHeader {
 unsigned short bfType;      // "BM"
 unsigned int   bfSize;      // ファイルサイズ
 unsigned short bfReserved1;    // 0
 unsigned short bfReserved2;    // 0
 unsigned int   bfOffBits;    // 画像データまでのオフセット
};

struct BitmapInfoHeader {
 unsigned int   biSize;      // 構造体のサイズ
 long           biWidth;      // 幅
 long           biHeight;    // 高さ
 unsigned short biPlanes;    // 1
 unsigned short biBitCount;    // ビット数
 unsigned int   biCompression;  // 圧縮方式
 unsigned int   biSizeImage;    // 画像データのサイズ
 long           biXPelsPerMeter;  // 水平解像度
 long           biYPelsPerMeter;  // 垂直解像度
 unsigned int   biClrUsed;    // 色数
 unsigned int   biClrImportant;  // 重要な色数
};

#pragma pack()

inline void WriteLine(const RGB *src, FILE *fp, int length)
{
 for(int i = 0; i < length; i++) {
 unsigned char buf[3] = {
 src->b,
 src->g,
 src->r
 };
 fwrite(buf, 3, 1, fp);
 src++;
 }
}

int LoadBitmap(const char *fileName, Image24 *dst)
{
 int i, linemod;
 BitmapFileHeader head;
 BitmapInfoHeader info;
 FILE *fp = NULL;

 fopen_s(&fp, fileName, "rb");

 if(fp == NULL) {
 printf("can not open %s!\n", fileName);
 return 0;
 }

 // read header
 fread(&head, sizeof(BitmapFileHeader), 1, fp);
 fread(&info, sizeof(BitmapInfoHeader), 1, fp);

 // undefine type
 if(head.bfType != ('B' | 'M' << 8)) {
 printf("no bitmap format %s!\n", fileName);
 fclose(fp);
 return 0;
 }

 dst->Create(info.biWidth, info.biHeight);

 if(info.biBitCount & ~(24)) {
 printf("biBitCount %d.\n", info.biBitCount);
 printf("%s Load failed!\n", fileName);
 fclose(fp);
 return 0;
 }

 linemod = ((info.biWidth * info.biBitCount) >> 3) & 3;

 for(i = 0; i < info.biHeight; i++) {
 switch(info.biBitCount) {
 case 24:
 ReadLine(dst->lines[info.biHeight - i - 1], fp, info.biWidth);
 break;
 }
 if(linemod != 0) fseek(fp, 4 - linemod, SEEK_CUR);
 }

 fclose(fp);
 printf("load finish\n");
 return 1;
}

だいたいセオリー通りの読み込み処理。読み込むフォーマットは24bitのものだけに対応している。注意点としては

  • #pragma pack(1)をしないとヘッダのサイズが正しくならない。
  • BGRの順に色が格納されている。
  • 下から上に向かって格納されている。
  • 1行のバイトサイズが4byteで割り切れない場合、パディングが入っている。

この辺に気をつければOK。

追記

ImageMagickで出力されたビットマップ画像だとヘッダの後ろに何か入っているようなのでちゃんと読み込めなかった。


コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

カテゴリー

%d人のブロガーが「いいね」をつけました。