tags:

views:

61

answers:

2

I've been having trouble with this for a while now, and I haven't gotten any solutions that work yet. Here is the problem, and the specifics:

I am loading a 256x256 uncompressed TGA into a simple OpenGL program that draws a quad on the screen, but when it shows up, it is shifted about two pixels to the left, with the cropped part appearing on the right side. It has been baffling me for the longest time, people have suggested clamping and such, but somehow I think my problem is probably something really simple, but I just can't figure out what it is!

Here is a screenshot comparing the TGA (left) and how it appears running in the program (right) for clarity. Also take note that there's a tiny black pixel on the upper right corner, I'm hoping that's related to the same problem.

alt text

Here's the code for the loader, I'm convinced that my problem lies in the way that I'm loading the texture.

Thanks in advance to anyone who can fix my problem.

bool TGA::LoadUncompressedTGA(char *filename,ifstream &texturestream)
{
 cout << "G position status:" << texturestream.tellg() << endl;
 texturestream.read((char*)header, sizeof(header));     //read 6 bytes into the file to get the tga header
 width  = (GLuint)header[1] * 256 + (GLuint)header[0];    //read and calculate width and save
 height = (GLuint)header[3] * 256 + (GLuint)header[2];    //read and calculate height and save
 bpp    = (GLuint)header[4];           //read bpp and save

 cout << bpp << endl;

 if((width <= 0) || (height <= 0) || ((bpp != 24) && (bpp !=32))) //check to make sure the height, width, and bpp are valid
 {
  return false;
 }
 if(bpp == 24)         
 {
  type = GL_RGB;
 }
 else
 {
  type = GL_RGBA;
 }
 imagesize = ((bpp/8) * width * height);          //determine size in bytes of the image
 cout << imagesize << endl;
 imagedata = new GLubyte[imagesize];           //allocate memory for our imagedata variable

 texturestream.read((char*)imagedata,imagesize);        //read according the the size of the image and save into imagedata 

 for(GLuint cswap = 0; cswap < (GLuint)imagesize; cswap += (bpp/8))         //loop through and reverse the tga's BGR format to RGB
 {
  imagedata[cswap] ^= imagedata[cswap+2] ^=                    //1st Byte XOR 3rd Byte XOR 1st Byte XOR 3rd Byte
     imagedata[cswap] ^= imagedata[cswap+2];
 }

 texturestream.close();              //close ifstream because we're done with it
 cout << "image loaded" << endl;

 glGenTextures(1, &texID);             // Generate OpenGL texture IDs
 glBindTexture(GL_TEXTURE_2D, texID);          

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

 glTexImage2D(GL_TEXTURE_2D, 0, type, width, height, 0, type, GL_UNSIGNED_BYTE, imagedata);



    delete imagedata;
 return true;
}

//Public loading function for TGA images.  Opens TGA file and determines 
//its type, if any, then loads it and calls the appropriate function.
//Returns: TRUE on success, FALSE on failure

bool TGA::loadTGA(char *filename)
{
 cout << width << endl;
 ifstream texturestream;
 texturestream.open(filename,ios::binary);
 texturestream.read((char*)header,sizeof(header));     //read 6 bytes into the file, its the header.                //if it matches the uncompressed header's first 6 bytes, load it as uncompressed
 LoadUncompressedTGA(filename,texturestream); 
 return true;
}
+2  A: 

It sure looks like you are consuming the header twice (once in TGA::loadTGA and then again in LoadUncompressedTGA).

But if that were the case then I'd think width, height, and bpp would all be radically wrong and it wouldn't look as correct as it does.

Jon-Eric
Yeah. To my knowledge, the header is actually 18 bytes long. I think my commentary is actually incorrect, but as you said, the image wouldn't have come in the way it did if I messed up the header that much. Definitely a spot to investigate, so thanks for the heads up.
Whynne
Well it looks like your hunch was correct. I checked out how far it was reading in and I noticed it read 24 bytes rather than the 18 it was supposed to. This was also causing me problems when loading alpha channel TGAs. Changed it and now everything works perfectly.Thank you so much. I knew it was something simple.
Whynne
+1  A: 

Here is a screenshot comparing the TGA (left) and how it appears running in the program (right) for clarity. Also take note that there's a tiny black pixel on the upper right corner, I'm hoping that's related to the same problem.

It looks like loading routine is broken - something obviously "eats" two pixels (assuming scanlines go from downside to upside). It is not an OPENGL problem, it is a bug somewhere in your loading routine.

I'm not familiar with *.tga format, but you may want to compare your loading routine with implementation from SDL_image library. As far as I know SDL_image loads images properly. Since your routine doesn't do that, it is bug in your routine. Compare your routine with working code in order to find the bug.

Be careful with licensing if you decide to copy SDL_image code into your project.

SigTerm
Yeah, I would much rather write the loading routine myself, and as I stated earlier, I know the problem is probably with my loading routine, I just can't seem to figure out what part of it is causing the shift. Thanks for the pointer, though.
Whynne