Sign in to follow this  

TGA loader bug/ need help please [Solved]

This topic is 3863 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey, I am trying to write a TGA loader for use with openGL. It compiles, but the texture only moderetly resembles the image file. It kind of looks like a picture on a tv with a bad reception. I of course have texCoords set up etc Can anyone see whats wrong? Thanks in advance! Heres the source code which I am compiling with visual studio 2003....
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <GL/glut.h>

const GLsizei windowWidth = 500;
const GLsizei windowHeight = 500;

bool createTexture();
bool loadTGA(char *texFileName);

GLfloat cubeRotateX = 45.0f;
GLfloat cubeRotateY = 45.0f;

struct TGA_header
{
	GLubyte ID_Length;
	GLubyte colorMapType;
	GLubyte imageType;
	GLubyte ColorMapSpecification[5];
	GLshort xOrigin;
	GLshort yOrigin;
	GLshort imageWidth;
	GLshort imageHeight;
	GLubyte pixelDepth;
};

char *imageData;
unsigned int bpp;
unsigned int width;
unsigned int height;
unsigned int texID;
char name[32];
GLuint type;

GLvoid establishProjectionMatrix(GLsizei width, GLsizei height)
{
	glViewport(0,0,width,height);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0f,(GLfloat)width/(GLfloat)height, 0.1f, 200.0f);
}

GLvoid initGL(GLsizei width, GLsizei height)
{
	establishProjectionMatrix(width,height);
	
	glClearColor(0.0f,0.0f,0.0f,0.0f);

	glShadeModel(GL_SMOOTH);

	glEnable (GL_LINE_SMOOTH);

	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);

	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
	glHint (GL_LINE_SMOOTH_HINT, GL_DONT_CARE);	

	glEnable(GL_TEXTURE_2D);

	loadTGA("ello.tga");
}

GLvoid displayFPS(GLvoid)
{
	static long lastTime=glutGet(GLUT_ELAPSED_TIME);
	static long loops=0;
	GLfloat fps =0.0f;

	int newTime = glutGet(GLUT_ELAPSED_TIME);

	if(newTime - lastTime > 100)
	{
		float newFPS = (float)loops/float(newTime - lastTime)*1000.0f;

		fps = (fps + newFPS)/2.0f;
		char title[80];
		sprintf(title,"Dave's OpenGl Cube Demo - %.2f",fps);

		glutSetWindowTitle(title);

		lastTime =newTime;

		loops =0;
	}
	loops++;
}

bool loadTGA(char *texFileName)
{
	GLuint i;
	GLuint temp;
	FILE *fp;

	struct TGA_header tgaHeader;

	if(!(fp=fopen(texFileName,"rb"))){
		printf("Failed to open file.\n");
		return 0;
	}

	fread((char*)&tgaHeader,1,sizeof(TGA_header),fp);

	if(tgaHeader.imageType !=2){
		printf("Unsuported TGA type.\n");
		return 0;
	}


	width = tgaHeader.imageWidth;
	height = tgaHeader.imageHeight;
	bpp = tgaHeader.pixelDepth;

	if (width <= 0 || height <= 0 || (bpp!=24 && bpp!=32)){
		printf("Wrong file type.\n");
		return 0;}

	GLuint bytesPerPixel = bpp / 8;
	GLuint imageSize = ((width * height) * bytesPerPixel);

	printf("W:%d, H: %d, BPP: %d, BytesPP: %d, Size: %d",width, height, bpp, bytesPerPixel, imageSize);
	
	type = GL_RGBA;

	if(bpp==24)
		type = GL_RGB;

	if((imageData = (char*)malloc(imageSize))==NULL){
		printf("Failed to allocate memory\n");
		return 0;
	}

	fread(imageData, 1, imageSize, fp);

	/*if(imageData == NULL)
	{
		free(imageData);
		return 0;
	}*/

	//Convert BGR to RGB
	for (i =0; i <(int)imageSize; i+=bytesPerPixel)
	{
		temp = imageData[i];
		imageData[i] = imageData[i+2];
		imageData[i+2] = temp;
	}

	createTexture();

	fclose(fp);

	return true;
}


bool createTexture()
{
	glGenTextures(1,&texID);
	glBindTexture(GL_TEXTURE_2D, texID);

	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

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

	return true;
}

GLvoid timerLoop(int value)
{
	glutPostRedisplay();

	glutTimerFunc(1,timerLoop,0);
}

GLvoid drawScene(GLvoid)
{
	int i;
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glMatrixMode(GL_MODELVIEW);

	glLoadIdentity();

	glTranslatef(0.0f, 0.0f, -5.0f);
	glRotatef(cubeRotateX,1,0,0);
	glRotatef(cubeRotateY,0,1,0);

	glBindTexture(GL_TEXTURE_2D, texID);
	
	glBegin(GL_POLYGON);

	glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f);
	glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
	glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
	glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, 1.0f, 1.0f);

	glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f);
	glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
	glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
	glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f);


	glEnd();

	glFlush();
	glutSwapBuffers();
	displayFPS();
}

int main (int argc, char *argv[])
{
	glutInit(&argc, argv);

	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);

	int windowID = glutCreateWindow("OpenGl Tetxure");
	glutReshapeWindow(windowWidth, windowHeight);

	initGL(windowWidth, windowHeight);

	glutDisplayFunc(drawScene);

	glutTimerFunc(1,timerLoop,0);

	glutMainLoop();

	return 0;
}




[Edited by - EndIsForever on May 20, 2007 4:18:23 AM]

Share this post


Link to post
Share on other sites
I am very tired today, so I'll let you do the work. Here is something I wrote a long time ago.

Header
class UTIL_EXPORT TGAReader : public ImageReader
{
public:
// constructor / deconstructor
TGAReader( void );
TGAReader( std::string &rFile );
virtual ~TGAReader( void );

// pure virtual overrides
virtual bool Read( std::string &rFile );
virtual bool Write( std::string &rFile );

private:
// private typedefs
#pragma pack( push, 1 )

typedef struct TGAHeaderTag
{
unsigned char m_nIdentSize; // Size of the ID that follows header
unsigned char m_nColorMapType; // Type of color map 0 = none, 1 = uses palletes
unsigned char m_nImageType; // 0 = none, 1 = indexed, 2 = rgb, 3 = grey, 8+ = rel packed
unsigned short m_nColorMapStart; // First color map entry in pallete
unsigned short m_nColorMapLength; // Number of colors in the pallete
unsigned char m_nColorMapBits; // Number of bits per pallete entry
unsigned short m_nXStart; // Image x origin
unsigned short m_nYStart; // Image y origin
unsigned short m_nWidth; // Image width in pixels
unsigned short m_nHeight; // Image height in pixels
unsigned char m_nBits; // Image bits per pexel 8, 16, 24, 32

union
{
struct
{
unsigned char m_nAttributeBits : 4; // Number of attributes associted to each pixel
unsigned char m_nReserved : 1; // Reserved
unsigned char m_nOrigin : 1; // 0 = lower left, 1 = upper left
unsigned char m_nInterleave : 2; // 00 = non-interleaved
// 01 = two-way interleaved
// 10 = four way interleaving
// 11 = reserved
} Bits;

unsigned char m_nDescriptor; // Image descriptor bits (vh flip bits)
} Descriptor;
} TGAHeader;

typedef union TGAColorTag
{
struct
{
unsigned char m_nBlue : 5;
unsigned char m_nGreenLow : 3;
unsigned char m_nGreenHigh : 2;
unsigned char m_nRed : 5;
unsigned char m_nAttribute : 1;
} TGA16Bit;

struct
{
unsigned char m_nBlue;
unsigned char m_nGreen;
unsigned char m_nRed;
} TGA24Bit;

struct
{
unsigned char m_nBlue;
unsigned char m_nGreen;
unsigned char m_nRed;
unsigned char m_nAttribute;
} TGA32Bit;
} TGAColor;

typedef struct TGARLECountTag
{
unsigned char m_nCount : 7;
unsigned char m_nRLEPacket : 1;
} TGARLECount;

#pragma pack( pop )

// private enums
enum ColorMapTypeEnum
{
CMT_NONE,
CMT_PALLETES
};

enum ImageTypeEnum
{
IT_NONE = 0,
IT_COLOR_MAPPED_UNCOMPRESSED = 1,
IT_RGB_UNCOMPRESSED = 2,
IT_BW_UNCOMPRESSED = 3,
IT_COLOR_MAPPED_RLE = 9,
IT_RGB_RLE = 10,
IT_BW_COMPRESSED = 11,
IT_COLOR_MAPPED_COMPRESSED_HUFFMAN_DELTA_RLE = 32,
IT_COLOR_MAPPED_COMPRESSED_HUFFMAN_DELTA_RLE_4QUAD = 33
};

// private member functions
bool ColorMappedUncompressed( const TGAHeader &rHeader,
std::ifstream &rFileStream );
bool RGBUncompressed( const TGAHeader &rHeader,
std::ifstream &rFileStream );
bool ColorMappedRLE( const TGAHeader &rHeader,
std::ifstream &rFileStream );
bool RGBRLE( const TGAHeader &rHeader,
std::ifstream &rFileStream );
};


bool TGAReader::Read( std::string &rFile )
{
// local(s)
bool bRead = false;
std::ifstream iStream;

// save the file name
m_sFileName = rFile;

// open the file to be read
iStream.open(rFile.c_str(), std::ios::ios_base::binary);

// make sure the file is open
if (iStream.is_open())
{
// local(s)
TGAHeader oHeader;

// read the header
iStream.read((char *)&oHeader, sizeof(TGAHeader));
// construct the image
switch (oHeader.m_nImageType)
{
case IT_COLOR_MAPPED_UNCOMPRESSED:
bRead = ColorMappedUncompressed(oHeader, iStream);
break;
case IT_RGB_UNCOMPRESSED:
bRead = RGBUncompressed(oHeader, iStream);
break;
case IT_COLOR_MAPPED_RLE:
bRead = ColorMappedRLE(oHeader, iStream);
break;
case IT_RGB_RLE:
bRead = RGBRLE(oHeader, iStream);
break;
case IT_COLOR_MAPPED_COMPRESSED_HUFFMAN_DELTA_RLE:
case IT_COLOR_MAPPED_COMPRESSED_HUFFMAN_DELTA_RLE_4QUAD:
case IT_BW_COMPRESSED:
case IT_BW_UNCOMPRESSED:
/* Not Supported By The Reader */
break;
}

// close the file
iStream.close();
}

return bRead;
}

bool TGAReader::Write( std::string &rFile )
{
return false;
}

bool TGAReader::ColorMappedUncompressed( const TGAHeader &rHeader,
std::ifstream &rFileStream )
{
// local(s)
bool bRead = false;
char cIDentField[256];
unsigned int unSize;

// determine if the ident field is used
if (rHeader.m_nIdentSize)
{
rFileStream.read(cIDentField, rHeader.m_nIdentSize);
}

// determine the new size
unSize = rHeader.m_nWidth * rHeader.m_nHeight;
// set the object data
m_oSize.m_nWidth = rHeader.m_nWidth;
m_oSize.m_nHeight = rHeader.m_nHeight;
// make sure that the color map is being used
if (rHeader.m_nColorMapType == CMT_PALLETES)
{
// local(s)
unsigned char *pColorPallete;
unsigned char *pIndexData;
unsigned char *pColorData;
unsigned int unColorTableSize;
unsigned char unBytesPerPixel;
Image *pImage;
double dRatio;

// create the new image
m_pImage = new Image[unSize];
// create pallete table
unBytesPerPixel = rHeader.m_nColorMapBits / 8;
unColorTableSize = rHeader.m_nColorMapLength * unBytesPerPixel;
pColorPallete = new unsigned char[unColorTableSize];
// read in the values for the pallete table
rFileStream.read((char *)pColorPallete, unColorTableSize);
// create the index scan line data
pIndexData = new unsigned char[rHeader.m_nWidth * rHeader.m_nBits / 8];
// set the data pointer
pImage = m_pImage;
// determine the ratio for 16 bit color maps
if (rHeader.m_nColorMapBits == 16)
{
dRatio = 255.0 / 31.0;
}
// read all the scan lines
for (unsigned int i = 0; i < rHeader.m_nHeight; i++)
{
// read the scan line
rFileStream.read((char *)pIndexData, rHeader.m_nWidth);
// determine each color
for (unsigned int j = 0; j < rHeader.m_nWidth; j++)
{
// find the color from the color map
pColorData = pColorPallete + pIndexData[j] * unBytesPerPixel;
// set the color values
switch (rHeader.m_nColorMapBits)
{
case 16:
pImage->m_nRed = (unsigned char)(((TGAColor *)pColorData)->TGA16Bit.m_nRed * dRatio);
pImage->m_nGreen = (unsigned char)((((TGAColor *)pColorData)->TGA16Bit.m_nGreenLow |
(((TGAColor *)pColorData)->TGA16Bit.m_nGreenHigh << 3)) * dRatio);
pImage->m_nBlue = (unsigned char)(((TGAColor *)pColorData)->TGA16Bit.m_nBlue * dRatio);
pImage->m_nAlpha = 0xFF;
break;
case 24:
pImage->m_nRed = ((TGAColor *)pColorData)->TGA24Bit.m_nRed;
pImage->m_nGreen = ((TGAColor *)pColorData)->TGA24Bit.m_nGreen;
pImage->m_nBlue = ((TGAColor *)pColorData)->TGA24Bit.m_nBlue;
pImage->m_nAlpha = 0xFF;
break;
case 32:
pImage->m_nRed = ((TGAColor *)pColorData)->TGA32Bit.m_nRed;
pImage->m_nGreen = ((TGAColor *)pColorData)->TGA32Bit.m_nGreen;
pImage->m_nBlue = ((TGAColor *)pColorData)->TGA32Bit.m_nBlue;
pImage->m_nAlpha = ((TGAColor *)pColorData)->TGA32Bit.m_nAttribute;
break;
}

// increase the image pointer
pImage++;
}
}

// delete the index data
delete [] pColorPallete;
delete [] pIndexData;
// image created data read
bRead = true;
}

return bRead;
}

bool TGAReader::RGBUncompressed( const TGAHeader &rHeader,
std::ifstream &rFileStream )
{
// local(s)
bool bRead = false;
char cIDentField[256];
unsigned int unSize;

// determine if the ident field is used
if (rHeader.m_nIdentSize)
{
rFileStream.read(cIDentField, rHeader.m_nIdentSize);
}

// determine the new size
unSize = rHeader.m_nWidth * rHeader.m_nHeight;
// set the object data
m_oSize.m_nWidth = rHeader.m_nWidth;
m_oSize.m_nHeight = rHeader.m_nHeight;

// make sure that a color map is not being used
if (rHeader.m_nColorMapType == CMT_NONE)
{
// local(s)
unsigned char *pScanLine, *pPixel,
unBytesPerPixel;
unsigned int unScanLineWidth;
double dRatio;
Image *pImage;

// create a new image
m_pImage = new Image[unSize];
// determine the scanline width
unBytesPerPixel = rHeader.m_nBits / 8;
unScanLineWidth = m_oSize.m_nWidth * unBytesPerPixel;
// create a scanline
pScanLine = new unsigned char[unScanLineWidth];
// set the pointer
pImage = m_pImage;
// determine if a ratio should be used
if (rHeader.m_nBits == 16)
{
dRatio = 255.0 / 31.0;
}

for (unsigned int i = 0;
i < m_oSize.m_nHeight;
i++)
{
// read the scan scanline
rFileStream.read((char *)pScanLine, unScanLineWidth);
// reset the pixel pointer
pPixel = pScanLine;

for (unsigned int j = 0;
j < m_oSize.m_nWidth;
j++)
{
// set the image
switch (rHeader.m_nBits)
{
case 16:
pImage->m_nRed = (unsigned char)(((TGAColor *)pPixel)->TGA16Bit.m_nRed * dRatio);
pImage->m_nGreen = (unsigned char)((((TGAColor *)pPixel)->TGA16Bit.m_nGreenLow |
(((TGAColor *)pPixel)->TGA16Bit.m_nGreenHigh << 3)) * dRatio);
pImage->m_nBlue = (unsigned char)(((TGAColor *)pPixel)->TGA16Bit.m_nBlue * dRatio);
pImage->m_nAlpha = 0xFF;
break;
case 24:
pImage->m_nRed = ((TGAColor *)pPixel)->TGA24Bit.m_nRed;
pImage->m_nGreen = ((TGAColor *)pPixel)->TGA24Bit.m_nGreen;
pImage->m_nBlue = ((TGAColor *)pPixel)->TGA24Bit.m_nBlue;
pImage->m_nAlpha = 0xFF;
break;
case 32:
pImage->m_nRed = ((TGAColor *)pPixel)->TGA32Bit.m_nRed;
pImage->m_nGreen = ((TGAColor *)pPixel)->TGA32Bit.m_nGreen;
pImage->m_nBlue = ((TGAColor *)pPixel)->TGA32Bit.m_nBlue;
pImage->m_nAlpha = ((TGAColor *)pPixel)->TGA32Bit.m_nAttribute;
break;
}

// increase the image pointers
pPixel += unBytesPerPixel;
pImage++;
}
}

// delete the scanline
delete [] pScanLine;
// image read
bRead = true;
}

return bRead;
}

bool TGAReader::ColorMappedRLE( const TGAHeader &rHeader,
std::ifstream &rFileStream )
{
// local(s)
bool bRead = false;
char cIDentField[256];
unsigned int unSize;

// determine if the ident field is used
if (rHeader.m_nIdentSize)
{
rFileStream.read(cIDentField, rHeader.m_nIdentSize);
}

// determine the new size
unSize = rHeader.m_nWidth * rHeader.m_nHeight;
// set the object data
m_oSize.m_nWidth = rHeader.m_nWidth;
m_oSize.m_nHeight = rHeader.m_nHeight;

// make sure a color map is being used
if (rHeader.m_nColorMapType == CMT_PALLETES)
{
// local(s)
unsigned char *pColorPallete;
unsigned char unScanLineWidth;
unsigned int unColorTableSize;
unsigned char unBytesPerColorPalleteIndex;
unsigned char unBytesPerPixel;
unsigned char *pScanLine, *pPixel;
TGARLECount oRLECount;
double dRatio;
Image *pImage;

// determine color table size
unBytesPerPixel = rHeader.m_nColorMapBits / 8;
unColorTableSize = unBytesPerPixel * rHeader.m_nColorMapLength;
// determine number of bytes per color index
unBytesPerColorPalleteIndex = rHeader.m_nBits / 8;
// create the color table
pColorPallete = new unsigned char[unColorTableSize];
// read in the pallete table
rFileStream.read((char *)pColorPallete, unColorTableSize);
// create the new image
pImage = m_pImage = new Image[unSize];
// determine the scan line width
unScanLineWidth = 0x80 * unBytesPerColorPalleteIndex;
// create the scan line
pScanLine = new unsigned char[unScanLineWidth];
// determine if a ratio needs to be applied
if (rHeader.m_nColorMapBits == 16)
{
dRatio = 255.0 / 31.0;
}

for (unsigned int i = 0;
i < m_oSize.m_nHeight;
i++)
{
for (unsigned int k = 0;
k < m_oSize.m_nWidth;
k++)
{
// read the rle count byte
rFileStream.read((char *)&oRLECount, sizeof(TGARLECount));
// determine the type of encoding being used
if (oRLECount.m_nRLEPacket)
{
// local(s)
unsigned int unIndex = 0;
unsigned char unPixel[4] = { 0x00, // Red
0x00, // Green
0x00, // Blue
0xFF }; // Alpha

// read the pixel packed into the one pixel value
rFileStream.read((char *)pScanLine, unBytesPerColorPalleteIndex);
// copy into index
memcpy(&unIndex, pScanLine, unBytesPerColorPalleteIndex);
// point to the color table
pPixel = pColorPallete + (unIndex * unBytesPerPixel);

// write the pixels to the image
switch (rHeader.m_nColorMapBits)
{
case 16:
unPixel[0] = (unsigned char)(((TGAColor *)pPixel)->TGA16Bit.m_nRed * dRatio);
unPixel[1] = (unsigned char)((((TGAColor *)pPixel)->TGA16Bit.m_nGreenLow |
((TGAColor *)pPixel)->TGA16Bit.m_nGreenHigh << 3) * dRatio);
unPixel[2] = (unsigned char)(((TGAColor *)pPixel)->TGA16Bit.m_nBlue * dRatio);
break;
case 24:
unPixel[0] = (unsigned char)((TGAColor *)pPixel)->TGA24Bit.m_nRed;
unPixel[1] = (unsigned char)((TGAColor *)pPixel)->TGA24Bit.m_nGreen;
unPixel[2] = (unsigned char)((TGAColor *)pPixel)->TGA24Bit.m_nBlue;
break;
case 32:
unPixel[0] = (unsigned char)((TGAColor *)pPixel)->TGA32Bit.m_nRed;
unPixel[1] = (unsigned char)((TGAColor *)pPixel)->TGA32Bit.m_nGreen;
unPixel[2] = (unsigned char)((TGAColor *)pPixel)->TGA32Bit.m_nBlue;
unPixel[3] = (unsigned char)((TGAColor *)pPixel)->TGA32Bit.m_nAttribute;
break;
}

// copy the pixel to the image
for (unsigned char j = 0;
j < oRLECount.m_nCount + 1;
j++)
{
memcpy(pImage++, unPixel, sizeof(Image));
}

// update the scan line pixel counter k
k += oRLECount.m_nCount;
}
else
{
// local(s)
unsigned int unIndex;

// read the number of pixels from the file
rFileStream.read((char *)pScanLine, unBytesPerColorPalleteIndex * (oRLECount.m_nCount + 1));

for (unsigned char j = 0;
j < oRLECount.m_nCount + 1;
j++)
{
unIndex = 0;
// copy into index
memcpy(&unIndex, pScanLine + (j * unBytesPerColorPalleteIndex), unBytesPerColorPalleteIndex);
// point to the color table
pPixel = pColorPallete + (unIndex * unBytesPerPixel);

// write the pixels to the image
switch (rHeader.m_nColorMapBits)
{
case 16:
pImage->m_nRed = (unsigned char)(((TGAColor *)pPixel)->TGA16Bit.m_nRed * dRatio);
pImage->m_nGreen = (unsigned char)((((TGAColor *)pPixel)->TGA16Bit.m_nGreenLow |
((TGAColor *)pPixel)->TGA16Bit.m_nGreenHigh << 3) * dRatio);
pImage->m_nBlue = (unsigned char)(((TGAColor *)pPixel)->TGA16Bit.m_nBlue * dRatio);
pImage->m_nAlpha = 0xFF;
break;
case 24:
pImage->m_nRed = (unsigned char)((TGAColor *)pPixel)->TGA24Bit.m_nRed;
pImage->m_nGreen = (unsigned char)((TGAColor *)pPixel)->TGA24Bit.m_nGreen;
pImage->m_nBlue = (unsigned char)((TGAColor *)pPixel)->TGA24Bit.m_nBlue;
pImage->m_nAlpha = 0xFF;
break;
case 32:
pImage->m_nRed = (unsigned char)((TGAColor *)pPixel)->TGA32Bit.m_nRed;
pImage->m_nGreen = (unsigned char)((TGAColor *)pPixel)->TGA32Bit.m_nGreen;
pImage->m_nBlue = (unsigned char)((TGAColor *)pPixel)->TGA32Bit.m_nBlue;
pImage->m_nAlpha = (unsigned char)((TGAColor *)pPixel)->TGA32Bit.m_nAttribute;
break;
}

// increase the image pointers
pImage++;
}

// update the scan line pixel counter k
k += oRLECount.m_nCount;
}
}
}

// delete temp objects
delete [] pColorPallete;
delete [] pScanLine;

bRead = true;
}

return bRead;
}

bool TGAReader::RGBRLE( const TGAHeader &rHeader,
std::ifstream &rFileStream )
{
// local(s)
bool bRead = false;
char cIDentField[256];
unsigned int unSize;

// determine if the ident field is used
if (rHeader.m_nIdentSize)
{
rFileStream.read(cIDentField, rHeader.m_nIdentSize);
}

// determine the new size
unSize = rHeader.m_nWidth * rHeader.m_nHeight;
// set the object data
m_oSize.m_nWidth = rHeader.m_nWidth;
m_oSize.m_nHeight = rHeader.m_nHeight;
// make sure that a color map is not being used
if (rHeader.m_nColorMapType == CMT_NONE)
{
// local(s)
Image *pImage;
double dRatio;
unsigned int unScanLineWidth;
unsigned char unBytesPerPixel;
unsigned char *pScanLine, *pPixel;
TGARLECount oRLECount;

// create a new image
m_pImage = new Image[unSize];
// determine the scanline width
unBytesPerPixel = rHeader.m_nBits / 8;
unScanLineWidth = 0x80 * unBytesPerPixel; /* 0x80 is the maximum pixel length */
// create a scanline
pScanLine = new unsigned char[unScanLineWidth];
// set the image pointer
pImage = m_pImage;
// determine if a ratio should be used
if (rHeader.m_nBits == 16)
{
dRatio = 255.0 / 31.0;
}

for (unsigned int i = 0;
i < m_oSize.m_nHeight;
i++)
{
for (unsigned int k = 0;
k < m_oSize.m_nWidth;
k++)
{
// read the rle count byte
rFileStream.read((char *)&oRLECount, sizeof(TGARLECount));
// determine the type of encoding being used
if (oRLECount.m_nRLEPacket)
{
// local(s)
unsigned char unPixel[4] = { 0x00, // Red
0x00, // Green
0x00, // Blue
0xFF }; // Alpha

// read the pixel packed into the one pixel value
rFileStream.read((char *)pScanLine, unBytesPerPixel);

// write the pixels to the image
switch (rHeader.m_nBits)
{
case 16:
unPixel[0] = (unsigned char)(((TGAColor *)pScanLine)->TGA16Bit.m_nRed * dRatio);
unPixel[1] = (unsigned char)((((TGAColor *)pScanLine)->TGA16Bit.m_nGreenLow |
((TGAColor *)pScanLine)->TGA16Bit.m_nGreenHigh << 3) * dRatio);
unPixel[2] = (unsigned char)(((TGAColor *)pScanLine)->TGA16Bit.m_nBlue * dRatio);
break;
case 24:
unPixel[0] = (unsigned char)((TGAColor *)pScanLine)->TGA24Bit.m_nRed;
unPixel[1] = (unsigned char)((TGAColor *)pScanLine)->TGA24Bit.m_nGreen;
unPixel[2] = (unsigned char)((TGAColor *)pScanLine)->TGA24Bit.m_nBlue;
break;
case 32:
unPixel[0] = (unsigned char)((TGAColor *)pScanLine)->TGA32Bit.m_nRed;
unPixel[1] = (unsigned char)((TGAColor *)pScanLine)->TGA32Bit.m_nGreen;
unPixel[2] = (unsigned char)((TGAColor *)pScanLine)->TGA32Bit.m_nBlue;
unPixel[3] = (unsigned char)((TGAColor *)pScanLine)->TGA32Bit.m_nAttribute;
break;
}

// copy the pixel to the image
for (unsigned char j = 0;
j < oRLECount.m_nCount + 1;
j++)
{
memcpy(pImage++, unPixel, sizeof(Image));
}

// update the scan line pixel counter k
k += oRLECount.m_nCount;
}
else
{
// read the number of pixels from the file
rFileStream.read((char *)pScanLine, unBytesPerPixel * (oRLECount.m_nCount + 1));
// reset the pixel pointer
pPixel = pScanLine;

for (unsigned char j = 0;
j < oRLECount.m_nCount + 1;
j++)
{
// write the pixels to the image
switch (rHeader.m_nBits)
{
case 16:
pImage->m_nRed = (unsigned char)(((TGAColor *)pPixel)->TGA16Bit.m_nRed * dRatio);
pImage->m_nGreen = (unsigned char)((((TGAColor *)pPixel)->TGA16Bit.m_nGreenLow |
((TGAColor *)pPixel)->TGA16Bit.m_nGreenHigh << 3) * dRatio);
pImage->m_nBlue = (unsigned char)(((TGAColor *)pPixel)->TGA16Bit.m_nBlue * dRatio);
pImage->m_nAlpha = 0xFF;
break;
case 24:
pImage->m_nRed = (unsigned char)((TGAColor *)pPixel)->TGA24Bit.m_nRed;
pImage->m_nGreen = (unsigned char)((TGAColor *)pPixel)->TGA24Bit.m_nGreen;
pImage->m_nBlue = (unsigned char)((TGAColor *)pPixel)->TGA24Bit.m_nBlue;
pImage->m_nAlpha = 0xFF;
break;
case 32:
pImage->m_nRed = (unsigned char)((TGAColor *)pPixel)->TGA32Bit.m_nRed;
pImage->m_nGreen = (unsigned char)((TGAColor *)pPixel)->TGA32Bit.m_nGreen;
pImage->m_nBlue = (unsigned char)((TGAColor *)pPixel)->TGA32Bit.m_nBlue;
pImage->m_nAlpha = (unsigned char)((TGAColor *)pPixel)->TGA32Bit.m_nAttribute;
break;
}

// increase the image pointers
pPixel += unBytesPerPixel;
pImage++;
}

// update the scan line pixel counter k
k += oRLECount.m_nCount;
}
}
}

// delete temp buffers
delete [] pScanLine;

bRead = true;
}

return bRead;
}

Share this post


Link to post
Share on other sites
Thanks for the reply. Unfortunately that isn't much use to me. I am using Visual Studio true enough but I am really coding C, not C++. Its for a university project, and the project has to be handed in, in C. The code needs to compile under the standard GCC compiler as well for my university to accept it. Its a lot to ask but you coulden't take a look at my code could you? :). Thanks....

Share this post


Link to post
Share on other sites
Any chance of a screenshot? There's a lot of patterns that we can recognise (Like incorrect scanline width, swapped R and B channels, etc).

Something you could try doing is dumping the data to a file as plain RGB, and importing it into Paint Shop Pro or Photoshop or something as a raw file. That should tell you if the data is being parsed correctly, but some OpenGL setup is screwing it up.

Share this post


Link to post
Share on other sites
It might be possible that you are not loading properly the TGA file. I see you tried to load the header with this

fread((char*)&tgaHeader,1,sizeof(TGA_header),fp);

However, you should read every field of the struct one by one. This is because there might be padding issues that make the read of the header not correct. To check that, debug it and check the values of the header struct fields after it was loaded.

Share this post


Link to post
Share on other sites
Hi, I compiled and ran your program in VC2005. It seems the loader isn't the problem but the way the vertices are specified for GL_POLYGON mode.

GL_POLYGON expects the vertices between glBegin/glEnd to define a single convex polygon. The vertices you wrote do not define a convex poly.

One solution is to break the rendering up into two seperate convex polygons.

glBegin(GL_POLYGON);
glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, 1.0f, 1.0f);
glEnd();

glBegin(GL_POLYGON);
glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f);
glEnd();


Or you can change GL_POLYGON to GL_QUADS in the original code and it will appear correctly.

I also added

glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

before glBegin() to test the alpha channel image.

I tested it with a uncompressed 24bit tga and a 32bit tga with an alpha channel.
ello24.tga
ello32.tga
Screenshot:
Before:
screenshot_before
After:
screenshot_after

[Edited by - Jack Sotac on May 19, 2007 1:15:32 PM]

Share this post


Link to post
Share on other sites
Jack, I could have your babies if that’s was something you would like :D. Seriously though I really appreciate that, and everyone else who contributed.

I added your modifications, and at first it didn't seem to make a difference, then I tried loading a different image and it worked perfectly! The only image still doesn’t work... its not compressed or anything like that, its really weird. But at least it works. Wooow.

Since I got someone to put a pic of the problem online, I might as well show you.... its still doing this even with the mods, other pics are fine tho!

www.scottishmondeoforum.com/dave/problem.jpg

Thanks again,
Dave.


Share this post


Link to post
Share on other sites
From the image, it looks to be a texture loading problem after all.[oh]

Things to check:

Make sure the image doesn't have a palette (tgaHeader.colorMapType should be 0). Some paint programs add one even if it's not used.

Set alignment explicitly before texture upload.
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_PACK_ALIGNMENT, 1);


Is the texture a power of two?

Read this, very old but good bad boy.
Avoiding 16 Common OpenGL Pitfalls

BTW, loadTGA() has a memory leak. After the call to createtexture()
you need to free the image memory free(imageData). It isn't needed anymore since the image has been uploaded to video memory.

Try the complete Nate Miller's tga loading code at texture.zip. Drop in his code and check the returned error code.

Good Luck.

Share this post


Link to post
Share on other sites

This topic is 3863 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this