Posted by & filed under diary, programming.


上手くいかない.

かれこれ2日,いろいろ試行錯誤してるけど未だに原因が特定できず.

もう fseek() で画像幅とか,必要な部分のみ取ってくるのでいいかなぁ…

とりあえず,動作テスト用にちっちゃな Bitmap 画像を用意した.

test

← 3×3 pixel 24bit bitmap 画像.

この画像の hexdump がこんな感じ.

42 4D 5A 00  00 00 00 00  00 00 36 00  00 00 28 00
00 00 03 00  00 00 03 00  00 00 01 00  18 00 00 00
00 00 24 00  00 00 00 00  00 00 00 00  00 00 00 00
00 00 00 00  00 00 1D E6  B5 00 F2 FF  A4 49 A3 00
00 00 27 7F  FF CC 48 3F  C9 AE FF 00  00 00 00 00
00 24 1C ED  4C B1 22 00  00 00

こいつをうまいこと読み込みたい.

読み込むコードはこんな感じ.

・ヘッダファイル

#pragma once

// include
#include <string>

typedef long  LONG;
typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef unsigned char BYTE;

// structure
/*BITMAPFILEHEADER*/
struct BITMAPFILEHEADER
{
	WORD  bfType;
	DWORD bfSize;
	WORD  bfReserved1;
	WORD  bfReserved2;
	DWORD bfOffBits;
};

/*BITMAPINFOHEADER*/
struct BITMAPINFOHEADER
{
	DWORD biSize; 
	LONG  biWidth;
	LONG  biHeight;
	WORD  biPlanes;
	WORD  biBitCount;
	DWORD biCompression;
	DWORD biSizeImage;
	LONG  biXPelsPerMeter;
	LONG  biYPelsPerMeter;
	DWORD biClrUsed;
	DWORD biClrImportant;
};

struct COLOR24
{
	BYTE b;
    BYTE g;
    BYTE r;
};

// class
class bmpTexture
{
private:
    unsigned int id; // Texture ID
    BYTE *data; // raw data
    unsigned int width, height;
    std::string filename;
    
    void init();
public:
    bmpTexture();
    bmpTexture(const std::string&, unsigned int);
    ~bmpTexture();
    BYTE* rawData(){return data;}
    unsigned int getTextureID(){return id;}
    unsigned int getWidth(){return width;}
    unsigned int getHeight(){return height;}
};

・プログラム本体

/*
 * class bmpTexture
 *
 * Desc: Bitmap画像ファイルからテクスチャを生成する
 */
bmpTexture::bmpTexture(const std::string& fname, unsigned int tid)
{
    filename = fname;
    id = tid;
    init();
}
bmpTexture::~bmpTexture()
{
    free(data);
}
void bmpTexture::init()
{
    FILE *fp;
    struct BITMAPINFOHEADER bmpih;
    struct BITMAPFILEHEADER bmpfh;
    struct COLOR24 rgb;
    BYTE dummy;
    BYTE *p;
    
    // Bitmapファイルオープン
    fp = fopen(filename.c_str(), "rb");
    if (!fp) {
        perror(filename.c_str());
        exit(EXIT_FAILURE);
    }

    // read header
    fread(&bmpfh, sizeof(BITMAPFILEHEADER), 1, fp);
    fread(&bmpih, sizeof(BITMAPINFOHEADER), 1, fp);
    
    // get info
    width  = bmpih.biWidth;
    height = bmpih.biHeight;
    if (bmpih.biBitCount != 24) {
        fprintf(stderr, "Not Bitmap24 file.n");
        exit(EXIT_FAILURE);
    }
    
    // メモリ確保
    data = new BYTE[width*height*3];
    
    // 画像データ読み込み
    p = data;
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            fread(&rgb, sizeof(COLOR24), 1, fp);
            *p = rgb.r; p++;
            *p = rgb.g; p++;
            *p = rgb.b; p++;
        }
        for (int j = 0; j < (width*3)%4; j++) {
            fread(&dummy, 1, 1, fp);
        }
    }
    
    // ファイルをクローズ
    fclose(fp);
    
    // テクスチャ登録
    glBindTexture(GL_TEXTURE_2D, id);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, width, height, GL_RGB, GL_UNSIGNED_BYTE, data);
}

だけど,何故か読み込んだ Bitmapfile が 24bit ファイルではないとのエラー表示を出す.

デバッガで BITMAPINFOHEADER の中身を見てみると,すべての値が1個ずつずれて代入されている状態.

biBitCount に入るべき 24 はそのひとつ前の biPlanes に入ってしまっていた.

そこで,BITMAPINFOHEADER よりも先に読み込む BITMAPFILEHEADER 構造体の中身を出力させてみると,

bfType: 0x4d42
bfSize: 0x00000000
bfReserved1: 0x0000
bfReserved2: 0x0036
bfOffbits: 0x00280000

・・なにかがおかしい.

bfSize が本来 0x0000005a となるところが, 0x00000000 になってしまっている.

読み込み時に一体何が起こっているのか…