Original Post
Hi all,
What I have done is taken the TGA loading tutorial on gametutorials.com and switched to using fstream instead of the standard C file routines. The uncompressed TGA displays fine, but the compressed one just shows a band of RGB noise on the top part and blank on the bottom.
My load function:
My create GL textures function:
Is there anything I''m doing wrong in either of those functions, that it would create the noise for the compressed texture?
Please don''t nitpick the code unless it''s related to this problem.
Thanks in advance
-----
For I have seen the face of evil and it will not soon be forgotten.
// Load a TGA file
bool OdinTGA::loadtga(const char *filename) {
short width = 0, height = 0;
char length = 0; // Length in bytes of pixels
char iType = 0; // Type of image(RLE, RGB, RGBA)
char bits = 0; // Bits per pixel of image
int channels = 0; // Number of channels
int stride = 0; // channels * width
ifstream tga(filename, ios::in | ios::binary);
if(tga.is_open() == false)
return false;
// Allocate memory for tgadata structure
tgadata = new otga_s[sizeof(otga_s)];
// Read in useful header information
tga.read(&length, sizeof(char)); // Read in the length of bytes from the header
tga.seekg(1, ios::cur); // Move ahead one byte
tga.read(&iType, sizeof(char)); // Read in image type
tga.seekg(9, ios::cur); // Move ahead nine bytes
// Read in width, height and bpp
tga.read((char *)&width, sizeof(short));
tga.read((char *)&height, sizeof(short));
tga.read((char *)&bits, sizeof(char));
// Move to the image data
tga.seekg(length + 1, ios::cur);
// Check if the image is RLE compressed or not
if(iType != TGA_RLE) {
// Check if the image is a 24 or 32-bit image
if(bits == 24 || bits == 32) {
// Calculate the channels(3 or 4)
// Then calculate stride and allocate memory for pixels
channels = bits / 8;
stride = channels * width;
tgadata->data = new unsigned char[stride * height];
// Load in the image data line by line
for(int y = 0; y < height; y++) {
// Store a pointer to current line
unsigned char *tmpline = &(tgadata->data[stride * y]);
tga.read((char *)tmpline, stride);
// Byte swapping between blue and red values
for(int i = 0; i < stride; i += channels) {
int temp = tmpline[i];
tmpline[i] = tmpline[i + 2];
tmpline[i + 2] = temp;
}
}
} else if(bits == 16) {
unsigned short pixels = 0;
int r = 0, g = 0, b = 0;
// Hardcode the channels since we are converting to 24-bit
channels = 3;
stride = channels * width;
tgadata->data = new unsigned char[stride * height];
for(int i = 0; i < width * height; i++) {
tga.read((char *)&pixels, sizeof(unsigned short));
// To convert we need to mask to isolate each colour value
// 0x1F = 11111 in binary, since 5 bits are reserved in
// each unsigned short for the R, G and B, we bit shift and
// mask. Shift up by 3 to get the full colour.
b = (pixels & 0x1F) << 3;
g = ((pixels >> 5) & 0x1F) << 3;
r = ((pixels >> 10) & 0x1F) << 3;
tgadata->data[i * 3 + 0] = r;
tgadata->data[i * 3 + 1] = g;
tgadata->data[i * 3 + 2] = b;
}
} else
return false;
} else {
// Run length encoded TGA file
char rleid = 0;
int coloursread = 0;
int i = 0;
channels = bits / 8;
stride = channels * width;
tgadata->data = new unsigned char[stride * height];
char *colours = new char[channels];
// Load in image data
while(i < width * height) {
// Read in current colour count + 1
tga.read(&rleid, sizeof(char));
// Is the string of colours encoded?
if(rleid < 128) {
rleid++;
while(rleid) {
tga.read(colours, sizeof(char) * channels);
// Store the current pixel in our image array
tgadata->data[coloursread + 0] = colours[2];
tgadata->data[coloursread + 1] = colours[1];
tgadata->data[coloursread + 2] = colours[0];
if(bits == 32)
tgadata->data[coloursread + 3] = colours[3];
i++;
rleid--;
coloursread += channels;
}
} else {
// Minus the 128 ID + 1(127) to get the colour count that needs
// to be read
rleid -= 127;
// Read in current colour
tga.read(colours, sizeof(char) * channels);
while(rleid) {
tgadata->data[coloursread + 0] = colours[2];
tgadata->data[coloursread + 1] = colours[1];
tgadata->data[coloursread + 2] = colours[0];
if(bits == 32)
tgadata->data[coloursread + 3] = colours[3];
i++;
rleid--;
coloursread += channels;
}
}
}
}
tga.close();
tgadata->channels = channels;
tgadata->width = width;
tgadata->height = height;
return true;
}
// Create an OpenGL texture from TGA
void OdinTGA::creategltex(const char *filename, int texID) {
if(!filename)
return;
if(loadtga(filename) == false)
return;
glGenTextures(1, &tID); // Generate a texture
glBindTexture(GL_TEXTURE_2D, tID);
// Set texture type to GL_RGB as default
int tType = GL_RGB;
if(tgadata->channels == 4)
tType = GL_RGBA;
// Build mipmaps
gluBuild2DMipmaps(GL_TEXTURE_2D, tgadata->channels, tgadata->width, tgadata->height, tType, GL_UNSIGNED_BYTE, tgadata->data);
// Setup quality of texture map
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
// Free image data
if(tgadata) {
if(tgadata->data)
delete[] tgadata->data;
delete tgadata;
}
}