Hi everybody ^^

I'm quite a newbie in loading image file, so I've try to improve myself by loading the TGA image structure (You can found it at http://en.wikipedia.org/wiki/Truevision_TGA , I'm quite believe in the information there)

My problem is after loading and draw it onto the screen using OpenGL ES, it's seem the image lost some stuff of... color chanel... I don't know how to describe this exactly but would you like to see my work compared to esUtil's feature and give me some advices ?

As you can see... The beautiful image is the result I want (converted from TGA to png), and the "green sky" lies with the ground up is my... creation >"<...

TextureLoader.cpp

esUtil_TGA.c

Attachments
//
// Book:      OpenGL(R) ES 2.0 Programming Guide
// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
// ISBN-10:   0321502795
// ISBN-13:   9780321502797
// Publisher: Addison-Wesley Professional
// URLs:      http://safari.informit.com/9780321563835
//            http://www.opengles-book.com
//

// esUtil_TGA.c
//
//    This file contains the Win32 implementation of a TGA image loader

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

///
//  Macros
//
#define INVERTED_BIT            (1 << 5)

///
//  Types
//
#pragma pack(push,x1)                            // Byte alignment (8-bit)
#pragma pack(1)

typedef struct
{
   unsigned char  IdSize,
                  MapType,
                  ImageType;
   unsigned short PaletteStart,
                  PaletteSize;
   unsigned char  PaletteEntryDepth;
   unsigned short X,
                  Y,
                  Width,
                  Height;
   unsigned char  ColorDepth,
                  Descriptor;
         
} TGA_HEADER;

#pragma pack(pop,x1)

////////////////////////////////////////////////////////////////////////////////////
//
//  Private Functions
//

////////////////////////////////////////////////////////////////////////////////////
//
//  Public Functions
//
//


///
//  WinTGALoad()
//
int WinTGALoad( const char *fileName, char **buffer, int *width, int *height )
{
   FILE        *fp;
   TGA_HEADER   Header;

   if ( fopen_s ( &fp, fileName, "rb" ) != 0 )
   {
      return FALSE;
   }

   if ( fp == NULL )
   {
      return FALSE;
   }

   fread ( &Header, sizeof(TGA_HEADER), 1, fp );

   *width = Header.Width;
   *height = Header.Height;
   
   if ( Header.ColorDepth == 24 )
   {
      RGBTRIPLE *Buffer24;

      Buffer24= (RGBTRIPLE*)malloc(sizeof(RGBTRIPLE) * (*width) * (*height));

      if(Buffer24)
      {
         int i=0;
         int x,
             y;

         fread(Buffer24, sizeof(RGBTRIPLE), (*width) * (*height), fp);

         *buffer= (LPSTR) malloc(3 * (*width) * (*height));

         for ( y = 0; y < *height; y++ )
            for( x = 0; x < *width; x++ )
            {
               int Index= y * (*width) + x;

               if(!(Header.Descriptor & INVERTED_BIT))
                  Index= ((*height) - 1 - y) * (*width) + x;

               (*buffer)[(i * 3)]=      Buffer24[Index].rgbtRed;
               (*buffer)[(i * 3) + 1]=  Buffer24[Index].rgbtGreen;
               (*buffer)[(i * 3) + 2]=  Buffer24[Index].rgbtBlue;
        
               i++;
            }
         
         fclose(fp);
         free(Buffer24);
         return(TRUE);
      }		
   }

   return(FALSE);
}
skybox_front.png 564.81 KB
//	Reference is at http://en.wikipedia.org/wiki/Truevision_TGA
//	And http://nehe.gamedev.net/tutorial/loading_compressed_and_uncompressed_tga%27s/22001/

#include <Windows.h>
#include <stdio.h>

#include "TextureLoader.h"

bool DEBUG = true;

void printTexInfo(Texture* texture)	{
	printf("Bits per pixel\t\t%i\n", texture->bpp);
	printf("Width         \t\t%i\n", texture->width);
	printf("Height        \t\t%i\n", texture->height);
	printf("Type          \t\t%x\n", texture->texType);
}

Texture* loadTexture(char* filename, Texture* (*loadFileType) (char*))	{
	if (DEBUG)	{
		if (!filename)	{
			printf("MISSING file name !\n");
			return NULL;
		}
	}

	return loadFileType(filename);
}

Texture* loadTGA(char* tgaName)	{
	FILE* file = NULL;

	Texture* tex = new Texture;
	tex->texID = 0;
	tex->bpp = 0;
	tex->height = 0;
	tex->texType = 0;
	tex->width = 0;
	tex->imageData = NULL;

	file = fopen(tgaName, "r");

	if (DEBUG)	{
		if (!file)	{
			printf("OPEN file failed !\n");
			return NULL;
		}
	}

	//	obtain file size
	fseek (file , 0 , SEEK_END);
	long fsize = ftell (file);
	rewind (file);

	//	copy the file into the buffer
	byte* buffer = (byte*) malloc ( fsize * sizeof(byte) );
	size_t result = fread (buffer, 1, fsize, file);

	//	read length of skipped fields
	//	higher byte * 256 + lower byte (little-endian)
	GLuint colorMapSize = buffer[6] * 256 + buffer[5];
	GLuint skipSize = buffer[0] + colorMapSize;

	//	read some necessary fields and store in our struct
	tex->width = buffer[13] * 256 + buffer[12];
	tex->height = buffer[15] * 256 + buffer[14];
	tex->bpp = (GLuint)buffer[16];

	//	read the core data
	//	!NOTE : with the compressed TGA, size is not simply w x h :D
	GLuint datasize = (tex->bpp/8) * tex->width * tex->height;
	tex->imageData = new GLubyte[datasize];
	for (int i = 17 + skipSize; i < 17 + skipSize + datasize; i ++)	{
		tex->imageData[i - 17 - skipSize] = buffer[i];
	}

	if(tex->bpp == 24)	tex->texType = GL_RGB;
	else				tex->texType = GL_RGBA;

	//	From NeHe : TGA files store their image in reverse order than what OpenGL wants
	//	So we must change the format from BGR to RGB. To do this we swap the first and third bytes in every pixel.
	for(GLuint i = 0; i < datasize; i += tex->bpp/8)	{
        // 1st Byte XOR 3rd Byte XOR 1st Byte XOR 3rd Byte
        tex->imageData[i] ^= tex->imageData[i+2];
		tex->imageData[i+2] ^= tex->imageData[i];
        tex->imageData[i] ^= tex->imageData[i+2];
		/*GLubyte b = tex->imageData[i];
		tex->imageData[i] = tex->imageData[i+2];
		tex->imageData[i+2] = b;*/
    }

	fclose(file);

	if (DEBUG)	{
		if (!tex)	{
			printf("CREATE texture failed !\n");
			return NULL;
		}
	}

	return tex;
}

Texture* loadBMP(char* bmpName);
Texture* loadJPG(char* jpgName);
Untitled.png 782.5 KB

Hi everybody ^^

I'm quite a newbie in loading image file, so I've try to improve myself by loading the TGA image structure (You can found it at http://en.wikipedia.org/wiki/Truevision_TGA, I'm quite believe in the information there)

My problem is after loading and draw it onto the screen using OpenGL ES, it's seem the image lost some stuff of... color chanel... I don't know how to describe this exactly but would you like to see my work compared to esUtil's feature and give me some advices ?

As you can see... The beautiful image is the result I want (converted from TGA to png), and the "green sky" lies with the ground up is my... creation >"<...

[ATTACH]22495[/ATTACH]

[ATTACH]22496[/ATTACH]

[ATTACH]22497[/ATTACH]

[ATTACH]22498[/ATTACH]

Try reading in binary mode by adding a "b". I'm guessing that's your problem.. the other two possibilities are that you're out of alignment when reading your bytes (i.e. if you didn't get the last byte of the header). Or that XOR thing isn't working--which seems a weird thing, but I don't have time to examine it closely. Let me know.. I'll bbl.

file = fopen(tgaName, "rb");

I've get last byte of the header but it 's seem... losing color chanel in other way :))
But... Amazing thing happened when I add two last bytes of the header to the front of my raw data : it worked !
Thank you for your advice, though I still want to know why we must add these bytes to our image data... All we have to do is just get all bytes in the "data" block of the TGA, don't we ?

I've get last byte of the header but it 's seem... losing color chanel in other way :))
But... Amazing thing happened when I add two last bytes of the header to the front of my raw data : it worked !
Thank you for your advice, though I still want to know why we must add these bytes to our image data... All we have to do is just get all bytes in the "data" block of the TGA, don't we ?

I *may* see the problem.

for (int i = 17 + skipSize; i < 17 + skipSize + datasize; i ++)

In order to skip the header portion, you would ignore 0 through 17. Meaning you would start at 18. Plus your skipsize. So if I'm right, when you added the last two bytes of the header to the front of your raw data, your first pixel is garbage since that's still part of the color map--you just didn't notice it because it alligned the rest of your raw data and the rest of the picture worked.

This article has been dead for over six months. Start a new discussion instead.