現在地 >> メニュー >> 基本編06 >> tga形式の画像 >> TGA画像読み込み

tga形式画像のヘッダ情報


「TGA形式の画像」は、「先頭の18ビット分(0〜17)」が「ヘッダ情報」である。


[参考]:TGA(targa形式)
http://www.shiojiri.ne.jp/~openspc/format/TGA/
※↑このページのカラーマップエントリー(2バイト)の後、「カラーマップの長さ(2バイト)」が抜けているようです。
(画像の横幅まで本当は12バイトある)


以下nehe production lesson 24 より

[準備]:データ構造の定義


以下のようなデータ構造を用意する

[画像用の構造体]

typedef struct                                                                          
{
        GLubyte *imageData; //イメージデータ(32ビットまで)                                                             
        GLuint  bpp;              // ビット/ピクセル
        GLuint  width;           // 横幅                                                                   
        GLuint  height;          // 高さ                                                                
        GLuint  texID;          //ID(複数使用時)                                                                  
} TextureImage;                                                                         



TGA画像の読み込み


無圧縮のtga画像の読み込みは、ヘッダ情報の読み込みの方が複雑。

― 手順 ―
  1. 先頭の12バイトを読み込んで、無圧縮のtgaヘッダと比較
  2. 次の6バイト内から縦・横のサイズ等の情報を取得
  3. 画像データを読み込む


[1]:先頭の12バイトを読み込んで比較



FILE *file = fopen("TGAimg.tga", "rb");
  ... ...
GLubyte  TGAheader[12]={0,0,2,0,0,0,0,0,0,0,0,0};//無圧縮のTGAヘッダ
GLubyte  TGAcompare[12]; //ヘッダ情報格納用(12バイト分)

fread(TGAcompare,1,sizeof(TGAcompare),file); //12バイトを読み込む

if (  memcmp(TGAheader , TGAcompare,  sizeof(TGAheader)  ) != 0 ) //12バイト分の比較
{
    return false;
}
 ... ...


[2]:次の6バイト分を読み込んで各種情報を取得



TextureImage *texture;
      ... ...
GLuint  bytesPerPixel;//(バイト/ピクセル)
GLubyte    header[6];

fread(header, 1, sizeof(header), file)  //次の6バイトを読み込む

 
texture->width  = header[1] * 256 + header[0];//TGA画像の幅を決定(上位バイト*256+下位バイト)
texture->height = header[3] * 256 + header[2];//TGA画像の高さの決定 (上位バイト*256+下位バイト)

//幅、高さが0じゃないかどうか?24ビットか、32ビットか?
if(texture->width  <= 0  ||  texture->height <= 0 || (header[4]!=24 && header[4]!=32) ) 
{
        fclose(file);    //エラー ならファイルを閉じる                                              
        return false;                                                           
}


texture->bpp  = header[4];//TGA画像のbppを取得(24か32か)
bytesPerPixel   = texture->bpp/8;  //何色あるかを計算(24/ 8 = 3色、   32/8  = 4色)


[3]:画像データを読み込む



GLuint  imageSize; //画像サイズ用 
GLuint  temp;     //一時データ用 

//必要なメモリ数を計算
imageSize = texture->width * texture->height * bytesPerPixel;   //(縦)×(横)×(3 or 4)

//メモリー確保
texture->imageData=(GLubyte *)malloc(imageSize);
if(texture->imageData==NULL)
{
    return false;
}

//画像データの読み込み
if( fread(texture->imageData, 1, imageSize, file) != imageSize)
{
        //正しく読み込めなかったら各種エラー処理
        if(texture->imageData!=NULL){                                            
            free(texture->imageData);
        }

        fclose(file);                                                           
        return false;                          

}

//BRG -> RGBの変換
for(GLuint i=0; i<int(imageSize); i+=bytesPerPixel)                             
{
        temp=texture->imageData[i];                                             
        texture->imageData[i] = texture->imageData[i + 2];
        texture->imageData[i + 2] = temp;                                       
}

fclose (file);


以上でデータ読み込みができる。

テクスチャへのコンバート


テクスチャへのコンバートで注意する点は、読み込んだtga画像が「RGB」か「RGBA」かを判断する点。


TextureImage *texture;
TextureImage    textures[1];
GLuint   type=GL_RGBA; //デフォルトは「RGBA」

... ...

glGenTextures(1, &texture[0].texID);
glBindTexture(GL_TEXTURE_2D, texture[0].texID);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

//もしも、24(ビット/ピクセル)の画像の時
if (texture[0].bpp==24)                                                         
{
        type=GL_RGB; //タイプ変更
}

glTexImage2D(GL_TEXTURE_2D, 0, type, texture[0].width, texture[0].height, 
                     0, type, GL_UNSIGNED_BYTE, texture[0].imageData);


まとめ


以上をまとめて、以下のように書ける

TextureImage    textures[1];

int LoadTGA(TextureImage *texture, char *filename)                                    
{    
        GLubyte   TGAheader[12]={0,0,2,0,0,0,0,0,0,0,0,0};//無圧縮のTGAヘッダ                        
        GLubyte   TGAcompare[12]; //ヘッダの比較用                                                 
        GLubyte   header[6];//ヘッダの最初の便利な6バイト用

        GLuint   bytesPerPixel;//(バイト/ピクセル)
        GLuint   imageSize; //画像サイズ用 
        GLuint   temp;     //一時データ用 
        GLuint   type=GL_RGBA; //デフォルトは「RGBA」(32bpp)                                                   


        //ファイルオープン
        FILE *file = fopen(filename, "rb");                                             

        if(file==NULL ||
            fread(TGAcompare,1,sizeof(TGAcompare),file)!=sizeof(TGAcompare) ||  //12バイトかどうかチェック
            memcmp(TGAheader,TGAcompare,sizeof(TGAheader))!=0 ||  //ヘッダファイルがただしいか?
            fread(header,1,sizeof(header),file)!=sizeof(header))  //よければ、次の6バイトを読む                    
        {
            if (file == NULL)                                                       
                    return false;
           else //何らかのエラー
           {
                    fclose(file);
                   return false;
           }
        }

        //TGA画像の幅を決定(上位バイト*256+下位バイト)              
        texture->width  = header[1] * 256 + header[0];

        //TGA画像の高さの決定 (上位バイト*256+下位バイト) 
        texture->height = header[3] * 256 + header[2];

        //幅、高さが0じゃないかどうか?24ビットか、32ビットか?
        if(texture->width  <=0 ||  texture->height <=0 || (header[4]!=24 && header[4]!=32))
        {
                //ミスったら、エラー
                fclose(file);                                                           
                return false;                                                           
        }

        //TGA画像のbppを取得(24か32か)
        texture->bpp  = header[4];

        bytesPerPixel   = texture->bpp/8; //色数を取得

        //イメージサイズの計算                                              
        imageSize = texture->width*texture->height*bytesPerPixel;                 

        //メモリー確保
       texture->imageData=(GLubyte *)malloc(imageSize);

       //メモリがとれたかをチェック
       if(texture->imageData==NULL || fread(texture->imageData, 1, imageSize, file)!=imageSize)
       {
                //メモリー開放
                if(texture->imageData!=NULL){                                            
                         free(texture->imageData);
                }

                fclose(file);
                return false;
      }

       for(GLuint i=0; i<int(imageSize); i+=bytesPerPixel)                             
        {                                                                                    
               //BRG -> RGBの変換
               temp=texture->imageData[i];                                             
               texture->imageData[i] = texture->imageData[i + 2];
               texture->imageData[i + 2] = temp;
        }

        fclose (file);


       //テクスチャ作成 IDで分ける
       glGenTextures(1, &texture[0].texID);                                            

       //バインドなど
       glBindTexture(GL_TEXTURE_2D, texture[0].texID);                                 
       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);               
       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);               


       //もしも、24(ビット/ピクセル)の画像の時
       if (texture[0].bpp==24)                                                         
       {
              type=GL_RGB;   //タイプ変更
       }

        glTexImage2D(GL_TEXTURE_2D, 0, type, texture[0].width, texture[0].height, 
                             0, type, GL_UNSIGNED_BYTE, texture[0].imageData);

        return true;                                                                    
}

目次

― その他 ―

Wiki内検索

計測中...(07.10.8〜)

Save The World






▲よろしければ広告のクリックもお願いします


▲ランキングに参加しました

管理人/副管理人のみ編集できます