TGA画像ファイルを扱う

■画像ファイルの種類

 画像形式のバイナリファイルは様々なフォーマットがあるが、主に使われているのが以下のものがある。 

BMP ・PNG ・JPG ・TGA

 

 簡単に各フォーマットの特性を挙げてみた。
BMP

→構造が単純で扱いやすい

→ファイルサイズが大きい

→半透明を扱えない


PNG

→データが圧縮される形式で扱いにくい

→ファイルサイズが小さい

→半透明を扱える


・JPG

→データが圧縮される形式で扱いにくい

→ファイルサイズが極めて小さい

→半透明を扱えない

 

そして今回はTGA形式について扱い方を紹介する。

・TGA形式とは

→Truevision Graphics Adapterの短縮語

→トゥルービジョン社が開発したラスタ―画像(ビットマップ画像とも呼ばれる、ピクセルを用いたもの)のファイル形式
→構造が単純で扱いやすい

→ファイルサイズが大きい

→半透明を扱える


・TGA形式の構造

→ファイルの先頭にTGAファイルヘッダと呼ばれる18バイトの画像情報が格納されている
オフセット0→ID Length→バイト数1→イメージIDデータのバイト数

オフセット1→Colormap Type→バイト数1→カラーマップの有無(0=無,1=有)

オフセット2→Image Type→バイト数1→画像記録形式( →0=画像データなし →1=圧縮無し、インデックスカラー画像 →2=圧縮無し、カラー画像 →3=圧縮無し、白黒画像 →9=圧縮あり、インデックスカラー画像 →10=圧縮あり、カラー画像 →11=圧縮あり、白黒画像)

オフセット3→First Entry Index→バイト数2→画像データのインデックス0に対するカラーマップのインデックス、カラーマップ無しの場合は未使用(常に0)

オフセット5→Colormap Length→バイト数2→カラーマップに登録されている色の数、同上

オフセット7→Colormap Entry Size→バイト数1→カラーマップに登録されている色一つのビット数、同上

オフセット8→X-origin→バイト数2→X座標をずらすピクセル

オフセット10→Y-origin→バイト数2→Y座標をずらすピクセル

オフセット12→Image Width→バイト数2→画像の横のピクセル

オフセット14→Image Height→バイト数2→画像の縦のピクセル

オフセット16→Pixel Depth→バイト数1→画像の1ピクセルのビット数

オフセット17→Image Descripter→バイト数1→画像の格納方向及び1ピクセルのアルファ要素のビット数


・TGA画像データからテクスチャ作成

→1.ファイルを開く 

→#include <fstream>  std::ifstream ifs;  ifs.open(filename, std::ios_base::binary);   

 2.TGAヘッダーを読み込む  

→uint8_t tgaHeader[18]; // TGAヘッダは18バイト   

 ifs.read(reinterpret_cast<char*>(tgaHeader), 18);


 3.イメージIDを読み込む/飛ばす  

→ifs.ignore(tgaHeader[0]);   

//ifs.read(char* buf_id, tgaHeader[0]);


 4.カラーマップを読み込む/飛ばす  

→要領は同じなので読み込む処理の詳細は割愛 

→if (tgaHeader[1]) {   

 const int colorMapLength = tgaHeader[5] + tgaHeader[6] * 0x100;   

 const int colorMapEntrySize = tgaHeader[7];   

 // エントリサイズはビット数なので、8で割ってバイト数に変換する   

 const int colorMapSize = (colorMapLength * colorMapEntrySize + 7) / 8;

 ifs.ignore(colorMapSize);   

}


 5.画像データを読み込む  

→const int width = tgaHeader[12] + tgaHeader[13] * 0x100;   

const int height = tgaHeader[14] + tgaHeader[15] * 0x100;   

const int pixelDepth = tgaHeader[16];   

const int imageSize = width * height * pixelDepth / 8;   

std::vector<uint8_t> buf(imageSize);   

ifs.read(reinterpret_cast<char*>(buf.data()), imageSize);


 6.読み込んだ画像データからテクスチャを作成する  

→// テクスチャオブジェクトを作成し、GPUメモリを確保する   

GLuint id;   

glCreateTextures(GL_TEXTURE_2D, 1, &id);   

glTextureStorage2D(id, 1, GL_RGBA8, width, height);   

//GPUメモリに転送する   

glTextureSubImage2D(id, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buf.data());      

GLuint tex = id;

 

以上。他のフォーマットについてもおいおい追加する予定。