I followed the NeHe tutorial to load TGA files, but I get some errors. I changed the code around a little bit because I’m making this class load other file formats. When I load uncompressed TGA files it works fine but when I try to load a compressed file I get the error “Error reading pixel” I’ve gone over the code countless times and I see nothing wrong with it.
Can someone please help me?
Thanks,
Nuke
class TEXTURE
{
private:typedef struct
{
GLubyte Header[6]; //holds the first 6 useful bytes of the file
GLuint bytesPerPixel; //number of BYTES Per Pixel (3 or 4)
GLuint imagesize; //amount of memory needed to hold the image
GLuint temp;
GLuint type; //the type of image, GL_RGB or GL_RGBA
GLuint h; //height of image
GLuint w; //width of image
GLuint bpp; //number of BITS Per Pixel (24, or 32)
} TGA;TGA tga; //used to store file info
bool LoadUncompressedTGA(FILE* file)
{
if(fread(tga.Header, sizeof(tga.Header), 1, file) == 0)
{
fprintf(stderr, "Error Opening UnCompressed TGA File
");
return false;
}x = tga.Header[1] * 256 + tga.Header[0]; y = tga.Header[3] * 256 + tga.Header[2]; bpp = tga.Header[4]; tga.w = x; tga.h = y; tga.bpp = bpp; if((x <= 0) | | (y <= 0) | | ((bpp != 24) && (bpp != 32))) { fprintf(stderr, "Error x, y, and/or, bpp has in invalid value
");
return false;
}if(bpp == 24) { type = GL_RGB; }else{ type = GL_RGBA; } tga.bytesPerPixel = (tga.bpp / 8); tga.imagesize = (tga.bytesPerPixel * tga.w * tga.h); //data = (GLubyte*)malloc(tga.imagesize); data = (char*)malloc(tga.imagesize); if(data == 0) { fprintf(stderr, "Error in memory!"); return false; } if(fread(data, 1, tga.imagesize, file) != tga.imagesize) { fprintf(stderr, "Image not the right size
", file);
return false;
}return true;
}
bool LoadCompressedTGA(FILE* file)
{
if(fread(tga.Header, sizeof(tga.Header), 1, file) == 0)
{
fprintf(stderr, "Error Opening UnCompressed TGA File
");
return false;
}x = tga.Header[1] * 256 + tga.Header[0]; y = tga.Header[3] * 256 + tga.Header[2]; bpp = tga.Header[4]; tga.w = x; tga.h = y; tga.bpp = bpp; if((x <= 0) | | (y <= 0) | | ((bpp != 24) && (bpp != 32))) { fprintf(stderr, "Error x, y, and/or, bpp has in invalid value
");
return false;
}if(bpp == 24) { type = GL_RGB; }else{ type = GL_RGBA; } tga.bytesPerPixel = (tga.bpp / 8); tga.imagesize = (tga.bytesPerPixel * tga.w * tga.h); //data = (GLubyte*)malloc(tga.imagesize); data = (char*)malloc(tga.imagesize); if(data == 0) { fprintf(stderr, "Error in memory!
");
return false;
}GLuint pixelcount = tga.h * tga.w; //number of pixels in the image GLuint currentpixel = 0; //current pixel we are reading data from GLuint currentbyte = 0; //current byte we are writing into imagedata //try char ! GLubyte GLubyte* colorbuffer = (GLubyte*)malloc(tga.bytesPerPixel); //storage for one pixel do { GLubyte chunkheader = 0; //var to store the value of the id chunk if(fread(&chunkheader, sizeof(GLubyte), 1, file) == 0) //try to read the chunks header { fprintf(stderr, "Error reading chunks header!
");
return false;
}if(chunkheader < 128) //if the chunk is a RAW chunk { chunkheader++; //add 1 to the value to get the total number of raw pixels //start pixel reading loop for(short counter = 0; counter < chunkheader; counter++) { //try to read 1 pixel if(fread(colorbuffer, 1, tga.bytesPerPixel, file) != tga.bytesPerPixel) { fprintf(stderr, "Error reading pixel 1
"); //the error is here
return false;
}data[currentbyte] = colorbuffer[2]; //write the 'R' byte data[currentbyte + 1] = colorbuffer[1]; //write the 'G' byte data[currentbyte + 2] = colorbuffer[0]; //write the 'B' byte //if its a 32bpp image if(tga.bytesPerPixel == 4) { data[currentbyte + 3] = colorbuffer[3]; //write the 'A' byte } currentbyte += tga.bytesPerPixel; //increment teh byte counter by the number of bytes per pixel currentpixel++; //increment by 1 } }else{ chunkheader -= 127; //subtract 127 to get rid of the id bit //read the next pixel if(fread(colorbuffer, 1, tga.bytesPerPixel, file) != tga.bytesPerPixel) { fprintf(stderr, "Error Reading Pixel 2
");
return false;
}//start the loop for(short counter =0; counter < chunkheader; counter++) { data[currentbyte] = colorbuffer[2]; //cpy the 'R' byte data[currentbyte + 1] = colorbuffer[1]; //cpy the 'G' byte data[currentbyte + 2] = colorbuffer[0]; // cpy the 'B' byte if(tga.bytesPerPixel == 4) { data[currentbyte + 3] = colorbuffer[3]; } } currentbyte += tga.bytesPerPixel; currentpixel++; } }while(currentpixel < pixelcount); fclose(file); return true;
}
public:
unsigned long x;
unsigned long y;
unsigned short int bpp;
char* data;
unsigned int ID;
GLuint type;TEXTURE()
{
type = GL_RGB;
}bool LoadTGA(char* FileName)
{
//find out if its compressed or not
GLubyte tgaheader[12];
//uncompressed tga header
GLubyte uTGAcompare[12] = {0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0};
//compressed tga header
GLubyte cTGAcompare[12] = {0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0 ,0};
FILE* file;file = fopen(FileName, "rb"); if(file == 0) { fprintf(stderr, "Error invalid TGA file: %s
", FileName);
return false;
}if(fread(&tgaheader, sizeof(tgaheader), 1, file) == 0) { fprintf(stderr, "Error invalid TGA file: %s
", FileName);
fclose(file);
return false;
}if(memcmp(uTGAcompare, &tgaheader, sizeof(tgaheader)) == 0) { fprintf(stderr, "loading uncompressed...
");
//load an uncompressed tga
if(LoadUncompressedTGA(file) == false)
{
fprintf(stderr, "Error Loading UnCompressed TGA File: %s
", FileName);
fclose(file);
return false;
}
}else if(memcmp(cTGAcompare, &tgaheader, sizeof(tgaheader)) == 0)
{
fprintf(stderr, "loading compressed…
");
//load compressed tga
if(LoadCompressedTGA(file) == false)
{
fprintf(stderr, "Error Loading Compressed TGA File: %s
", FileName);
fclose(file);
return false;
}
}else{
fprintf(stderr, "Error invalid TGA file: %s
", FileName);
fclose(file);
return false;
}fclose(file); return true;
}
/*
“Both width and height must have the form 2^m + 2b, where m is a non-negative integer (which can have a
different value for width than for height) and b is the value of border. The maximum size of a texture
map depends on the implementation of OpenGL, but it must be at least 64 x 64 (or 66 x 66 with borders).”
–OpenGL Programming GuideMeaning: You can use width or height of 2, 4, 8, 16, 32, 64, (on new video cards) 128, 256, 512 (They dont have to be the same) If you have a texture border you add 2 to the size.
/
int LoadTexture(char FileName)
{if(LoadTGA(FileName) == 0) { return 0; } glGenTextures(1, &ID); glBindTexture(GL_TEXTURE_2D, ID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, 3, x, y, 0, type, GL_UNSIGNED_BYTE, data); return 1;
}
};