C++ OpenGL TGA加载失败
我一直在通过加载TGA文件的基本OpenGl教程,将其用作3D对象上的纹理。我已经能够从TGA头部加载数据,但是当我尝试加载实际的图像数据时,它失败了。我不确定它出错的地方。这里是我的纹理加载类:C++ OpenGL TGA加载失败
头文件
struct TGA_Header
{
GLbyte ID_Length;
GLbyte ColorMapType;
GLbyte ImageType;
// Color map specifications
GLbyte firstEntryIndex[2];
GLbyte colorMapLength[2];
GLbyte colorMapEntrySize;
//image specification
GLshort xOrigin;
GLshort yOrigin;
GLshort ImageWidth;
GLshort ImageHeight;
GLbyte PixelDepth;
GLbyte ImageDescriptor;
};
class Texture
{
public:
Texture(string in_filename, string in_name = "");
~Texture();
public:
unsigned short width;
unsigned short height;
unsigned int length;
unsigned char type;
unsigned char *imageData;
unsigned int bpp;
unsigned int texID;
string name;
static vector<Texture *> textures;
private:
bool loadTGA(string filename);
bool createTexture(unsigned char *imageData, int width, int height, int type);
void swap(unsigned char * ori, unsigned char * dest, GLint size);
void flipImage(unsigned char * image, bool flipHorizontal, bool flipVertical, GLushort width, GLushort height, GLbyte bpp);
};
这里是在CPP负载TGA功能:
bool Texture::loadTGA(string filename)
{
TGA_Header TGAheader;
ifstream file(filename.data(), std::ios::in, std::ios::binary);
//make sure the file was opened properly
if (!file.is_open())
return false;
if(!file.read((char *)&TGAheader, sizeof(TGAheader)))
return false;
//make sure the image is of a type we can handle
if(TGAheader.ImageType != 2)
return false;
width = TGAheader.ImageWidth;
height = TGAheader.ImageHeight;
bpp = TGAheader.PixelDepth;
if(width < 0 || // if the width or height is less than 0, than
height <= 0 || // the image is corrupt
(bpp != 24 && bpp != 32)) // make sure we are of the correct bit depth
{
return false;
}
//check for an alpha channel
GLuint type = GL_RGBA;
if (bpp == 24)
type = GL_RGB;
GLuint bytesPerPixel = bpp/8;
//allocate memory for the TGA so we can read it
GLuint imageSize = width * height * bytesPerPixel;
imageData = new GLubyte[imageSize];
if (imageData == NULL)
return false;
//make sure we are in the correct position to load the image data
file.seekg(-imageSize, std::ios::end);
// if something when wrong, make sure we free up the memory
//NOTE: It never gets past this point. The conditional always fails.
if (!file.read((char *)imageData, imageSize))
{
delete imageData;
return false;
}
//more code is down here, but it doesnt matter because it does not pass the above function
}
这似乎加载一些数据,但它一直返回该它失败了。任何帮助为什么将不胜感激。如果它有点罗嗦,但我不确定什么是或不重要。
更新: 所以,我只是重写了函数。我使用的ifste似乎是问题的原因。具体来说,它会尝试加载比我输入的更多的字节数据。我不知道行为的原因,但我已在下面列出了我的功能代码。感谢大家的帮助。
因此,我从使用ifstream更改为FILE。 ifstream正试图加载比我在参数中列出的更多的字节。这是新的代码。 (注:它仍然需要optomized。我相信有一些未使用的变量浮动,但它完美的工作。)。再次感谢大家的帮助。
头文件:
//struct to hold tga data
struct TGA_Header
{
GLbyte ID_Length;
GLbyte ColorMapType;
GLbyte ImageType;
// Color map specifications
GLbyte firstEntryIndex[2];
GLbyte colorMapLength[2];
GLbyte colorMapEntrySize;
//image specification
GLshort xOrigin;
GLshort yOrigin;
GLshort ImageWidth;
GLshort ImageHeight;
GLbyte PixelDepth;
GLbyte ImageDescriptor;
};
class Texture
{
public:
//functions
Texture(string in_filename, string in_name = "");
~Texture();
public:
//vars
unsigned char *imageData;
unsigned int texID;
string name;
//temp global access point for accessing all loaded textures
static vector<Texture *> textures;
private:
//can add additional load functions for other image types
bool loadTGA(string filename);
bool createTexture(unsigned char *imageData, int width, int height, int type);
void swap(unsigned char * ori, unsigned char * dest, GLint size);
void flipImage(unsigned char * image, bool flipHorizontal, bool flipVertical, GLushort width, GLushort height, GLbyte bpp);
};
#endif
这里是负载TGA功能:
bool Texture::loadTGA(string filename)
{
//var for swapping colors
unsigned char colorSwap = 0;
GLuint type;
TGA_Header TGAheader;
FILE* file = fopen(filename.c_str(), "rb");
unsigned char Temp_TGAheader[18];
//check to make sure the file loaded
if(file == NULL)
return false;
fread(Temp_TGAheader, 1, sizeof(Temp_TGAheader), file);
//pull out the relavent data. 2 byte data (short) must be converted
TGAheader.ID_Length = Temp_TGAheader[0];
TGAheader.ImageType = Temp_TGAheader[2];
TGAheader.ImageWidth = *static_cast<unsigned short*>(static_cast<void*>(&Temp_TGAheader[12]));
TGAheader.ImageHeight = *static_cast<unsigned short*>(static_cast<void*>(&Temp_TGAheader[14]));
TGAheader.PixelDepth = Temp_TGAheader[16];
//make sure the image is of a type we can handle
if(TGAheader.ImageType != 2 || TGAheader.ImageWidth <= 0 || TGAheader.ImageHeight <= 0)
{
fclose(file);
return false;
}
//set the type
if (TGAheader.PixelDepth == 32)
{
type = GL_RGBA;
}
else if (TGAheader.PixelDepth == 24)
{
type = GL_RGB;
}
else
{
//incompatable image type
return false;
}
//remember bits != bytes. To convert we need to divide by 8
GLuint bytesPerPixel = TGAheader.PixelDepth/8;
//The Memory Required For The TGA Data
unsigned int imageSize = TGAheader.ImageWidth * TGAheader.ImageHeight * bytesPerPixel;// Calculate
//request the needed memory
imageData = new GLubyte[imageSize];
if (imageData == NULL) // just in case
return false;
if(fread(imageData, 1, imageSize, file) != imageSize)
{
//Kill it
delete [] imageData;
fclose(file);
return false;
}
fclose(file);
for (unsigned int x = 0; x < imageSize; x +=bytesPerPixel)
{
colorSwap = imageData[x];
imageData[x] = imageData[x + 2];
imageData[x + 2] = colorSwap;
}
createTexture(imageData, TGAheader.ImageWidth, TGAheader.ImageHeight, type);
return true;
}
我不熟悉C++,很抱歉。
您确定该行file.seekg(-imageSize, std::ios::end);
不应该是file.seekg(headerSize, std::ios::start);
?
从头开始比从头开始更有意义。
您还应该检查ColorMapType != 0
。
P.S.这里的if(width < 0 || height <=0
宽度检查也应该是<=
。
我曾尝试过: file.seekg(18,std :: ios :: beg); 但是由于它似乎没有影响结果,所以我将它改回来了。 – Donutfiend84 2012-01-13 06:31:39
我不认为这是一个很好的做法,坚持只在明显错位的情况下才“正常工作”的解决方案。在这种情况下,它应该是'beg'和某种'SizeOf(tgaHeader)'而不是'18'。至于问题 - 调试器是你的朋友 - 检查你有什么'file.read'错误。 – Kromster 2012-01-13 06:51:39
你也应该检查'ColorMapType!= 0' – Kromster 2012-01-13 07:46:37
该问题可能取决于不支持压缩TGA的TGA算法。
确保您不压缩TGA,并且TGA顺序(较不重要)位于左下角原点。
我通常使用GIMP,并在相同的时刻,取消RLE压缩并放置左下对齐。
这就是为什么有一个检查:'如果(TGAheader.ImageType!= 2)返回false;'。类型2代表未压缩的TGA。如果TGA顺序颠倒,它不会影响加载,只是在渲染中颠倒显示图像。 – Kromster 2012-01-13 07:45:04
你是怎么从调试学到了什么? – 2012-01-13 06:00:05
不幸的是,并不多。 imageData指针肯定会加载某种类型的数据,但它无论如何都会失败。 – Donutfiend84 2012-01-13 06:34:34
请注意,您应该使用'delete [] imageData',虽然 – rotoglup 2012-01-13 07:00:09