Here's my TGA reading code. Note that the code is actually supposed to be designed to take either a 24-bit truecolor TGA or an 8-bit indexed TGA, but right now I'm just testing the reading of a 24-bit truecolor TGA.
int loadTGAToTexture(string filePath, HSTexture * hsTex)
{
//the data that OpenGL ultimately needs
GLushort imageWidth = 0;
GLushort imageHeight = 0;
GLenum format = GL_RGB;
GLubyte * imageData;
GLuint textureID;
GLuint bufferID;
//variables to help us get the above data
FILE * file;
GLubyte imageIDLength;
GLubyte colorMapType;
GLubyte imageType;
GLushort colorMapLength;
GLubyte colorMapEntrySize;
GLubyte pixelDepth;
GLubyte bytesPerPixel;
GLubyte imageDescriptor;
bool topAlign = true;
bool rightAlign = true;
//open the file
if(GLuint error = fopen_s(&file, filePath.data(), "rb") != 0)
{
return error; //couldn't open the file
}
//gather all the general info about the TGA file
fseek(file, 0L, SEEK_SET); //move to the beginning of the file
fread(&imageIDLength, 1, 1, file); //get the length of the image id field
fread(&colorMapType, 1, 1, file); //see if the file has a color map in it or not
fread(&imageType, 1, 1, file); //find out what kind of image file this is
if(imageType == 9)
{
format = GL_COLOR_INDEX; //its an indexed RLE format
}
else if(imageType != 10)
{
return -1; //this needs to be RLE, either indexed or truecolor
}
fseek(file, 2L, SEEK_CUR); //skip the first two bytes of the color map specification
fread(&colorMapLength, 2, 1, file); //get the length of the color map
fread(&colorMapEntrySize, 1, 1, file); //get the size of each color map entry
if(colorMapEntrySize == 15)
{
colorMapEntrySize = 16; //make sure it's a multiple of 8
}
fseek(file, 4L, SEEK_CUR); //skip the first four bytes of the image specification
fread((void *)&imageWidth, 2, 1, file); //get the image width
fread((void *)&imageHeight, 2, 1, file); //get the image height
fread(&pixelDepth, 1, 1, file); //get the size of each pixel in bits
bytesPerPixel = pixelDepth/8; //get the size of each pixel in bytes
if((format == GL_COLOR_INDEX && pixelDepth != 8) || (format == GL_RGB && pixelDepth != 24))
{
return -1; //only allowed configurations are: indexed with 8-bit, or truecolor with 24 bit
}
fread(&imageDescriptor, 1, 1, file); //get the image descriptor, and pull some data from it
if((imageDescriptor & ATTRIBUTE_BITS) > 0)
{
return -1; //no attributes should be defined
}
if((imageDescriptor & TOP_ALIGN) == 0)
{
topAlign = false; //the pixels are bottom-aligned
}
if((imageDescriptor & RIGHT_ALIGN) == 0)
{
rightAlign = false; //the pixels are left-aligned
}
fseek(file, (long)imageIDLength, SEEK_CUR); //skip the imageID
if(colorMapType != 0)
{
fseek(file, (long)(colorMapLength * colorMapEntrySize), SEEK_CUR); //skip the color map data
}
//okay, time for the fun part: picking through the image data.
//it's ALWAYS going to be in RLE format so we can't just grab the raw data.
GLuint maxPixels = imageWidth * imageHeight; //we need this so we know when to stop
GLuint curPixels = 0; //keeps track of how far we've gone through the actual pixels
imageData = (GLubyte*)malloc(maxPixels * bytesPerPixel); //set up our image data buffer
GLubyte repCount; //this'll hold each repetition count field
GLubyte * runColor = (GLubyte*)malloc(bytesPerPixel); //create a buffer to hold the color data of a run
while(curPixels < maxPixels)
{
if(fread(&repCount, 1, 1, file) != 1) { return -1;} //get the repetition count field
if((repCount & RL_PACKET) == 0)
{
//this is a raw packet.
//Just shove the pixel data into the image data buffer
repCount = repCount & REP_COUNT_BITS; //get the actual number of following pixels
//put the pixels into the image data buffer
for(int i = 0; i <= repCount; i++)
{
//fread(imageData + (curPixels * bytesPerPixel) + (i * bytesPerPixel), bytesPerPixel, 1, file);
for(int j = bytesPerPixel - 1; j >= 0; j--)
{
//gotta read each individual pixel in backwards since TGA stores color backwards
if(fread(imageData + (curPixels * bytesPerPixel) + (i * bytesPerPixel) + j, 1, 1, file) != 1) { return -1; }
}
}
}
else
{
//this is a run-length packet.
//Put the specificed number of pixels of the specified color into the image data buffer
repCount = repCount & REP_COUNT_BITS; //get the actual number of following pixels
//get the color if this run
//fread(runColor, bytesPerPixel, 1, file);
for(int i = bytesPerPixel - 1; i >= 0; i--)
{
//since TGA stores colors as BGR, we need to read it backwards to get RGB
if(fread(runColor + i, 1, 1, file) != 1) { return -1; }
}
for(int i = 0; i <= repCount; i++)
{
//put a pixel of the specified packet color into the image data buffer
memcpy(imageData + (curPixels * bytesPerPixel) + (i * bytesPerPixel), runColor, bytesPerPixel);
}
}
curPixels += repCount + 1; //update how far we've moved through the actual pixels
}
fclose(file);
delete(runColor);
//create and bind the texture
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
//set some options
//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
//put everything in the texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, imageWidth, imageHeight, 0, format, GL_UNSIGNED_BYTE, imageData);
delete(imageData);
glBindTexture(GL_TEXTURE_2D, 0);
//make an array of coordinates based on the texture dimensions
GLshort * dim = new GLshort[12];
dim[0] = 0; dim[1] = 0; dim[2] = 0;
dim[3] = imageWidth; dim[4] = 0; dim[5] = 0;
dim[6] = imageWidth; dim[7] = imageHeight; dim[8] = 0;
dim[9] = 0; dim[10] = imageHeight; dim[11] = 0;
//make a buffer object
glGenBuffers(1, &bufferID);
glBindBuffer(GL_ARRAY_BUFFER, bufferID);
glBufferData(GL_ARRAY_BUFFER, 12*sizeof(GLushort), dim, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
delete[] dim;
//now, put all the results in the texture struct
hsTex->defined = true;
hsTex->textureID = textureID;
hsTex->bufferID = bufferID;
hsTex->rightAlign = rightAlign;
hsTex->topAlign = topAlign;
return 0;
}
Attached are four files. test.bmp and john.bmp is what the files look like before being turned into a 24 bit compressed truecolor TGA (I know that part of the process works fine because I can open them back up in a TGA viewer and they look correct) and then run through my code. testResult.bmp and johnResult.bmp is what I get back out as an on-screen texture. I'm rendering in orthographic mode and the surface I'm drawing on has the same dimensions as the texture that belongs to it.
Any ideas? Any help would be appreciated.
[attachment=7142:test.bmp]
[attachment=7143:testResult.bmp]
[attachment=7140:john.bmp]
[attachment=7141:johnResult.bmp]