一、TGA文件相关介绍
通过前面的博客
我们了解了什么是TGA文件,现在我们来正式介绍一下C++中如何加载TGA文件?
二、如何加载TGA文件?
2.1 定义一个结构体TGA_HEADER
定义这个结构体的时候,得注意内存对齐方式,否则读取出来的TGA文件是有错误的。 具体的坑参考下面的博客:
typedef struct
__attribute__ ( ( packed ) )
{
unsigned char IdSize,
MapType,
ImageType;
unsigned short PaletteStart,
PaletteSize;
unsigned char PaletteEntryDepth;
unsigned short X,
Y,
Width,
Height;
unsigned char ColorDepth,
Descriptor;
} TGA_HEADER;
2.2 加载Assets目录下的TGA文件
一般我们的TGA文件放在assets目录下,如下所示: 可以参考下面的博客,加载assets目录下的文件:
下面的代码是:从assets目录下下载了指定的assets目录下的相对文件路径的TGA文件。 如何转换成Texture纹理。
-
GLUtils::loadTgaTexture 方法 GLUtils::loadTgaTexture 方法 用来加载 TGA图片并转换为纹理 -
GLUtils::loadTgaTexture 方法 调用了 GLUtils::lesLoadTGA 方法 GLUtils::lesLoadTGA 方法用来读取TGA文件并转换成 char * -
GLUtils::lesLoadTGA 方法 调用了 GLUtils::esFileOpen 方法和GLUtils::esFileClose 方法 GLUtils::esFileOpen 方法和GLUtils::esFileClose 方法 分别是打开和关闭assets目录下的指定文件 其中esFile 是AAsset -
完整代码如下
#include <android/asset_manager_jni.h>
typedef AAsset esFile;
static esFile *esFileOpen ( const char *fileName )
{
AAssetManager* nativeManager = AAssetManager_fromJava(sEnv, sAssetManager);
if (nativeManager == nullptr) {
return nullptr;
}
return AAssetManager_open(nativeManager, fileName, AASSET_MODE_BUFFER);
}
static void esFileClose ( esFile *pFile )
{
if ( pFile != nullptr )
{
AAsset_close ( pFile );
}
}
static int esFileRead ( esFile *pFile, int bytesToRead, void *buffer )
{
int bytesRead = 0;
if ( pFile == nullptr )
{
return bytesRead;
}
bytesRead = AAsset_read ( pFile, buffer, bytesToRead );
return bytesRead;
}
char * esLoadTGA (const char *fileName, int *width, int *height )
{
char *buffer;
esFile *fp;
TGA_HEADER Header;
int bytesRead;
fp = esFileOpen (fileName );
if ( fp == nullptr )
{
LOGE ( "esLoadTGA FAILED to load : { %s }\n", fileName )
return nullptr;
}
LOGD ( "sizeof ( TGA_HEADER ) : { %d }\n", sizeof ( TGA_HEADER ) )
bytesRead = esFileRead ( fp, sizeof ( TGA_HEADER ), &Header );
*width = Header.Width;
*height = Header.Height;
if ( Header.ColorDepth == 8 ||
Header.ColorDepth == 24 || Header.ColorDepth == 32 )
{
int bytesToRead = sizeof ( char ) * ( *width ) * ( *height ) * Header.ColorDepth / 8;
buffer = ( char * ) malloc ( bytesToRead );
if ( buffer )
{
bytesRead = esFileRead ( fp, bytesToRead, buffer );
esFileClose ( fp );
return ( buffer );
}
}
return ( nullptr );
}
GLuint GLUtils::loadTgaTexture (const char *fileName )
{
int width, height;
char *buffer = esLoadTGA (fileName, &width, &height );
GLuint texId;
if ( buffer == nullptr )
{
LOGI ( "Error loading (%s) image.\n", fileName )
return 0;
}
glGenTextures ( 1, &texId );
glBindTexture ( GL_TEXTURE_2D, texId );
glTexImage2D ( GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, buffer );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
free ( buffer );
return texId;
}
2.3 使用它
使用方式很简单,之间调用下面的方法,参数传文件相对路径即可
textureId = GLUtils::loadTgaTexture("texture/heightmap.tga");
最终我们加载并显示出来的效果如下: 具体效果实现参考GitHub:https://github.com/ouyangpeng/OpenGLESDemo.git 找到代码: src/main/cpp/sample/texture/TerrainRender.cpp 查看效果实现
|