Error while reading TGA file and doing Texture Cube map

In my program, i read a TGA file with a function like this:

char* LoadTGA(char* filename, int* width, int* height, int* bpp);


As you can see, this function: return a char array of image data (without TGA file header, from the first pixel row of image to the last pixel row of image), width of TGA image, height of TGA image, and bits per pixel of image data. The part of code that read image data is this:

    int w = pHeader->width; //width of image
int h = pHeader->height;  // height of image
int rowSize = w * pHeader->bits / 8;   //The bit is bits per pixel
bool bInverted = ( (pHeader->descriptor & (1 << 5)) != 0 );  //My TGA image is not inverted so bInverted is false.
for ( int i = 0; i < h; i ++ )
{
char * pSrcRow = pSrc +
( bInverted ? ( h - i - 1 ) * rowSize : i * rowSize );
if ( pHeader->bits == 24 )
{
for ( int j = 0; j < w; j ++ )
{
*pDest ++ = pSrcRow[2];
*pDest ++ = pSrcRow[1];
*pDest ++ = pSrcRow[0];
pSrcRow += 3;
}
}
}


As this code show, for my TGA image, which have bits per pixel (bpp) equals to 24, not inverted, the return char array will be from the first pixel row of image to the last pixel row of image.

I read a image of 512 x 384 pixels like this image below:

I use this image for texture cube so i read 6 parts of this image in following function:

bool Texture::SplitTextureCube(int i, char* des)
{
int l, m, size = width/4;
int aTopLeft[][2] = {{size*2, size}, {0, size}, {size, 0}, {size, size*2}, {size, size}, {size*3, size}};
int rowSize = height * bpp / 8;
for (int j = 0; j < size; j++ ) //height
{
char * pSrcRow = imageData + (aTopLeft[i][2] + j) * rowSize + aTopLeft[i][0];
if ( bpp == 24 )
{
for ( int k = 0; k < size; k ++ )   //width
{
*des ++ = pSrcRow[0];
*des ++ = pSrcRow[1];
*des ++ = pSrcRow[2];
pSrcRow += 3;
}
}
else
{
for ( int k = 0; k < size; k ++ )
{
*des ++ = pSrcRow[m + 0];
*des ++ = pSrcRow[m + 1];
*des ++ = pSrcRow[m + 2];
*des ++ = pSrcRow[m + 3];
pSrcRow += 4;
}
}
}
return true;
}


This function is called as below:

 char *face = new char[width/4 * height/3 * bpp/8];
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_CUBE_MAP, textureId);
for (int i=0; i<6; i++)
{
SplitTextureCube(i, face);
glTexImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_X+i, 0, GL_RGB, width/4, height/3, 0, GL_RGB, GL_UNSIGNED_BYTE, face);
//glTexImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_X+i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, imageData);
}
delete [] face;


I guess you need no more explain. The problem is when my program running, my cube texture is disordered like this:

I sure that problems are inside my "SplitTextureCube" function, i sure that i read pixels in the wrong order, please help me fix that function.

I spotted a couple of problems with these two lines in SplitTextureCube:

int rowSize = height * bpp / 8;
...
char * pSrcRow = imageData + (aTopLeft[i][2] + j) * rowSize + aTopLeft[i][0];


They should be:

int rowSize = width * bpp / 8;
...
char * pSrcRow = imageData + (aTopLeft[i][1] + j) * rowSize + aTopLeft[i][0];


Also, in that function you have l and m variables that are never initialized, but m is used as an offset in the 32-bit case, which is presumably not intended.

That's surely contributing to the problem. Beyond that it's possible you'll have to rotate some of the faces as well as cropping them out of the horizontal cross image. I don't know off the top of my head which faces need to be rotated which way, but it should be obvious once the above problems are fixed.

• i have tried "int rowSize = width * bpp / 8;" before but it still isn't correct way, so i change it to height for trying and then i forget to change it back to "width". "aTopLeft[i][2]" is a typo error. In my code it actually is "aTopLeft[i][1]". – Linh Dao Oct 11 '13 at 1:05

I've solved it. Here is the right code for "SplitTextureCube" function:

bool Texture::SplitTextureCube(int i, char* des)
{
int size = width/4;
int aTopLeft[][2] = {   {size * 2 * bpp / 8, size},     //0
{0, size},                      //1
{size * bpp / 8, 0},            //2
{size * bpp / 8, size*2},       //3
{size * bpp / 8, size},         //4
{size * 3 * bpp / 8, size}      //5
};
int rowSize = width * bpp / 8;
for (int j = 0; j < size; j++ ) //height
{
char * pSrcRow = imageData + (aTopLeft[i][1] + j) * rowSize + aTopLeft[i][0];
if ( bpp == 24 )
{
for ( int k = 0; k < size; k ++ )   //width
{
*des ++ = pSrcRow[0];
*des ++ = pSrcRow[1];
*des ++ = pSrcRow[2];
pSrcRow += 3;
}
}
else
{
for ( int k = 0; k < size; k ++ )
{
*des ++ = pSrcRow[0];
*des ++ = pSrcRow[1];
*des ++ = pSrcRow[2];
*des ++ = pSrcRow[3];
pSrcRow += 4;
}
}
}
return true;
}