TOP

ABOUT

PROGRAM

DIALY







テクスチャを読み込む!!(2)

 1.はじめに…
 今回は,Truevision Image Format すなわち,Targaファイル(*.tga)の読み込みについてやってみます。
TGAのフォーマットでは圧縮と無圧縮があるのですが,24Bitと32Bitの無圧縮形式についてのみ取り上げます。




 2.TGAファイルフォーマット
 まず,ファイルを読み込むにあたってファイルフォーマットを知らなければ読み込むプログラムは作れません。
とりあえずTGAフォーマットについていくつか書かれているサイトがあったので,それを元に説明してみますが,あくまでもネットから拾ってきた情報なので正しいとは限らないので注意してください。
TGAファイルフォーマットは次のように定義されているようです(24bit,32bit無圧縮)。



◆ヘッダー部は0x0000のID field lengthから0x0011のDiscipterまで18バイトあります。
◆データ部は0x0012から始まります
◆フッター部はデータ部のおわりから始まり,26バイトあります。


 3.ファイルの読み込み
 色々と書いてありますが,読み込む上で大事なのは,ビット数,画像の幅と高さ,ピクセルデータこれらがわかっていれば読み込むことができます。逆にこれがわかっていないと読み込む上で非常に困ります。
上の表でいうと,Image widthとImage heightとBit per pixelが画像の幅・高さ,ビット数に対応し, ピクセルデータは0x0012から順に格納されています。
よって,読み込む際はまず18バイトあるヘッダー部を読み込む変数を用意しておいて,ヘッダー部だけまず読み取ります。
つぎに,読み取ったヘッダーからImage widthとImage heightとBit per pixelに該当する部分を参照し,これらからピクセルデータのデータサイズを計算し,その分だけメモリを確保します。
ピクセルデータのデータサイズは…
(ピクセルデータのサイズ)=(画像の幅)×(画像の高さ)×(1ピクセルあたりのバイト数)
で求めます。
メモリを確保できたら,ピクセルデータを読み取っていきます。ピクセルデータは計算でデーターサイズ分あるので,for文でぐるんぐるん回しながら読み取っていきます。
ピクセルデータは格納方向などをいじっていなければBGR(A)の順で左から右。上から下へと行くようになっているので,読み取ったあとにBGR(A)をRGB(A)の順に変換する操作を忘れずにしてください。この操作を行わなかった場合,色がおかしくなります。
読み込みを行うクラスはTGALoader.hで次にように定義しました。
//
// include
//
#include <iostream>
#include <GL/glut.h>
using namespace std;

//////////////////////////////////////////////////////////////////////////
//  TGALoader class
//////////////////////////////////////////////////////////////////////////
class TGAImage
{
protected:
    GLuint imageSize;
    GLubyte *imageData;
    GLenum format;
    GLuint internalFormat;
    GLuint width;
    GLuint height;
    GLuint bpp;

public:
    GLuint ID;
    TGAImage();
    ~TGAImage();
    bool ReadTGA(const char *filename);
    GLuint Load(const char *filename);
};
で,中身はTGALoader.cppで次のような感じで書いてあります。
//-----------------------------------------------------------------------------------------------------
//  ReadTGA
//  Desc : TGAファイルの読み込み
//-----------------------------------------------------------------------------------------------------
bool TGAImage::ReadTGA(const char *filename)
{
    FILE *fp;
    GLubyte header[18]; 
    GLubyte bytePerPixel;
    GLuint temp;

    // ファイルを開く
    if ( (fp = fopen(filename,"rb")) == NULL )
    {
        cout << "Error : 指定したファイルを開けませんでした\n";
        cout << "File Name : " << filename << endl;
        return false;
    }

    // ヘッダー情報の読み込み
    fread(header, 1, sizeof(header), fp);
    
    // 幅と高さを決める
    width = header[13] * 256 + header[12];
    height = header[15] * 256 + header[14];
    
    // ビットの深さ
    bpp = header[16];

    // 24 bit
    if ( bpp == 24 )
    {
        format = GL_RGB;
        internalFormat = GL_RGB;
    }
    // 32 bit
    else if ( bpp = 32 )
    {
        format = GL_RGBA;
        internalFormat = GL_RGBA;
    }

    // 1ピクセル当たりのバイト数を決定
    bytePerPixel = bpp/8;

    // データサイズの決定
    imageSize = width * height * bytePerPixel;

    // メモリを確保
    imageData = new GLubyte[imageSize];

    // テクセルデータを一気に読み取り
    fread(imageData, 1, imageSize, fp);

    // BGR(A)をRGB(A)にコンバート
    for ( int i=0; i<(int)imageSize; i+=bytePerPixel )
    {
        temp = imageData[i];
        imageData[i+0] = imageData[i+2];
        imageData[i+2] = temp;
    }

    // ファイルを閉じる
    fclose(fp);

    return true;
}

//-----------------------------------------------------------------------------------------------------
//  Load
//  Desc : TGAファイルを読み込み,テクスチャを生成
//-----------------------------------------------------------------------------------------------------
GLuint TGAImage::Load(const char *filename)
{
    // ファイル読み込み
    if ( !ReadTGA(filename) )
        return false;

    // テクスチャを生成
    glGenTextures(1, &ID);

    // テクスチャをバインド
    glBindTexture(GL_TEXTURE_2D, ID);

    // 
    if ( bpp == 24 ) glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
    else if ( bpp == 32 ) glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    // テクスチャの割り当て
    gluBuild2DMipmaps(GL_TEXTURE_2D, internalFormat, width, height, format, GL_UNSIGNED_BYTE, imageData);

    // テクスチャを拡大・縮小する方法の指定
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

    // テクスチャ環境
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

    // メモリ解放
    if ( imageData )
    {
        delete [] imageData;
        imageData = NULL;
    }
    return ID;
}
OpenGL側でのテクスチャの設定とかは前回のRAWの読み込みとほぼ同じです。
ものすごい手抜きですけど,一応こんな感じで無圧縮24bitと32bitのTGAファイルは読み込むことができると思います。


 Download
本ソースコードおよびプログラムを使用したことによる如何なる損害も製作者は責任を負いません。
本ソースコードおよびプログラムは自己責任でご使用ください。
プログラムの作成にはMicrosoft Visual Studio 2005 Professional Editionを用いています。