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;
以上。他のフォーマットについてもおいおい追加する予定。