#include "ExCImageLoader.h"


ExCImageLoader::ExCImageLoader(void)
{
}

ExCImageLoader::ExCImageLoader(std::string FileName)
{
	LoadImage(FileName);
}

ExCImageLoader::~ExCImageLoader(void)
{
	delete m_data;
	delete m_palette;
}

TextureType ExCImageLoader::FindTextureType(std::string FileName)
{
Guard(TextureType ExCImageLoader::FindTextureType(std::string FileName))
	//std::cout<<FileName<<std::endl;
	//Extension in string
	if(FileName.find("."))
	{
		if(FileName.find(".bmp")==(FileName.length()-4))return BMP;
		if(FileName.find(".tga")==(FileName.length()-4))return TGA;
		if(FileName.find(".pcx")==(FileName.length()-4))return PCX;
		//if(FileName.find(".jpg")==(FileName.length()-4))return JPG;
		//if(FileName.find(".rgb")==(FileName.length()-4))return RGB;
		//if(FileName.find(".raw")==(FileName.length()-4))return RAW;
		if(FileName.find(".dds")==(FileName.length()-4))return DDS;
		if(FileName.find(".ppm")==(FileName.length()-4))return PPM;
		if(FileName.find(".")<FileName.length())return UNKNOWN;
	}
	//No extension in string
	//std::cout<<"File without extension"<<std::endl;
	FILE *file;
	std::ifstream filetest;
	std::string strFileName;
	
	//try with bmp
	strFileName=FileName+".bmp";
	if ((file = fopen(strFileName.data(), "r"))!=NULL){fclose(file);return BMP;}
    //try with pcx
	strFileName=FileName+".pcx";
	if ((file = fopen(strFileName.data(), "r"))!=NULL){fclose(file);return PCX;}
	//try with tga
	strFileName=FileName+".tga";
	if ((file = fopen(strFileName.data(), "r"))!=NULL){fclose(file);return TGA;}
	//try with ppm
	strFileName=FileName+".ppm";
	if ((file = fopen(strFileName.data(), "r"))!=NULL){fclose(file);return PPM;}
	//try with dds
	strFileName=FileName+".dds";
	if ((file = fopen(strFileName.data(), "r"))!=NULL){fclose(file);return DDS;}
	/*
	//try with jpg
	strFileName=FileName+".jpg";
	if ((file = fopen(strFileName.data(), "r"))!=NULL){fclose(file);return JPG;}
	//try with rgb
	strFileName=FileName+".rgb";
	if ((file = fopen(strFileName.data(), "r"))!=NULL){fclose(file);return RGB;}
	//try with raw
	strFileName=FileName+".raw";
	if ((file = fopen(strFileName.data(), "r"))!=NULL){fclose(file);return RAW;}
	*/
	throw ExCExpFileNotFound();
	return UNKNOWN;
UnGuard
}

bool ExCImageLoader::LoadImage(std::string FileName)
{
Guard(bool ExCImageLoader::LoadImage(std::string FileName))
	m_TextureType=FindTextureType(FileName);
	//std::cout<<m_TextureType;
	switch(m_TextureType)
	{
	case BMP:return LoadBMP(FileName);
	case TGA:return LoadTGA(FileName);
	case PCX:return LoadPCX(FileName);
	case JPG:return LoadJPG(FileName);
	//case RGB:return LoadRGB(FileName);
	//case RAW:return LoadRAW(FileName);
	case DDS:return LoadDDS(FileName);
	case PPM:return LoadPPM(FileName);
	case UNKNOWN:return false;
	default:return false;
	}
UnGuard
}
/*
bool ExCImageLoader::LoadImage(const char *strFileName)
{
Guard(bool ExCImageLoader::LoadImage(const char *strFileName))
return LoadImage(std::string(*strFileName) );
UnGuard
}*/
bool ExCImageLoader::LoadRAW(std::string strFileName)
{
	return false;
}

bool ExCImageLoader::LoadRGB(std::string strFileName)
{
	return false;
}

bool ExCImageLoader::LoadJPG(std::string strFileName)
{
	
	return false;
}

bool ExCImageLoader::LoadDDS(std::string strFileName)
{
Guard(bool ExCImageLoader::LoadDDS(std::string strFileName))
	m_TextureType = DDS;
	DDSURFACEDESC2 ddsd;
	char filecode[4];
	FILE *fp;
	int factor;

	strFileName=strFileName+".dds";
	fp = fopen(strFileName.data(), "rb");
	if (!fp) 
	{
		throw ExCExpFileNotFound();
		return NULL;
	}

	/* verify the type of file */
	fread(filecode, 1, 4, fp);
	if (strncmp(filecode, "DDS ", 4) != 0) 
	{
		fclose(fp);
		return NULL;
	}

	/* get the surface desc */
	fread(&ddsd, sizeof(ddsd), 1, fp);

	switch(ddsd.ddpfPixelFormat.dwFourCC)
	{
	case FOURCC_DXT1:
		m_ddsFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
		factor = 2;
		break;
	case FOURCC_DXT3:
		m_ddsFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
		factor = 4;
		break;
	case FOURCC_DXT5:
		m_ddsFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
		factor = 4;
		break;
	default:
		return NULL;
	}

	/* how big is it going to be including all mipmaps? */
	m_ddsBufsize = ddsd.dwMipMapCount > 1 ? ddsd.dwLinearSize * factor : ddsd.dwLinearSize;
//	unsigned char buffinverse;
//	buffinverse = (unsigned char*)malloc(m_ddsBufsize * sizeof(unsigned char));
	m_data = (unsigned char*)malloc(m_ddsBufsize * sizeof(unsigned char));
	
	fread(m_data, 1, m_ddsBufsize, fp);
	/* close the file pointer */
	fclose(fp);


	//inverse pixel



	m_sizeX       = ddsd.dwWidth;
	m_sizeY     = ddsd.dwHeight;
	m_ddsComponent = (ddsd.ddpfPixelFormat.dwFourCC == FOURCC_DXT1) ? 3 : 4;
	m_ddsNumMipmaps = ddsd.dwMipMapCount;
	return true;
UnGuard
}

bool ExCImageLoader::LoadPPM(std::string strFileName)
{
Guard(bool ExCImageLoader::LoadPPM(std::string strFileName))
	FILE* fp;
    int i, w, h, d;
    char head[70];          /* max line <= 70 in PPM (per spec). */
    
	strFileName=strFileName+".ppm";

    fp = fopen(strFileName.data(), "rb");
    if (!fp) 
	{
		std::cout<<strFileName<<std::endl;
		throw ExCExpFileNotFound();
        return NULL;
    }
    
    /* grab first two chars of the file and make sure that it has the
       correct magic cookie for a raw PPM file. */
    fgets(head, 70, fp);
    if (strncmp(head, "P6", 2)) 
	{
        printf("%s: Not a raw PPM file\n", strFileName.data());
        return NULL;
    }
    
    /* grab the three elements in the header (width, height, maxval). */
    i = 0;
    while(i < 3) {
        fgets(head, 70, fp);
        if (head[0] == '#')     /* skip comments. */
            continue;
        if (i == 0)
            i += sscanf(head, "%d %d %d", &w, &h, &d);
        else if (i == 1)
            i += sscanf(head, "%d %d", &h, &d);
        else if (i == 2)
            i += sscanf(head, "%d", &d);
    }
    
    /* grab all the image data in one fell swoop. */
    m_data = (unsigned char*)malloc(sizeof(unsigned char)*w*h*3);
    fread(m_data, sizeof(unsigned char), w*h*3, fp);
    fclose(fp);
    
    m_sizeX = w;
    m_sizeY = h;
    
	
	return true;
UnGuard
}

bool ExCImageLoader::LoadTGA(std::string strFileName)
{
Guard(bool ExCImageLoader::LoadTGA(std::string strFileName))
	WORD width = 0, height = 0;			// The dimensions of the image
	byte length = 0;					// The length in bytes to the pixels
	byte imageType = 0;					// The image type (RLE, RGB, Alpha...)
	byte bits = 0;						// The bits per pixel for the image (16, 24, 32)
	FILE *pFile = NULL;					// The file pointer
	int channels = 0;					// The channels of the image (3 = RGA : 4 = RGBA)
	int stride = 0;						// The stride (channels * width)
	int i = 0;							// A counter

	strFileName=strFileName+".tga";
	// Open a file pointer to the targa file and check if it was found and opened 
	if((pFile = fopen(strFileName.data(), "rb")) == NULL) 
	{
		// Display an error message saying the file was not found, then return NULL
		std::cout<<strFileName<<std::endl;
		throw ExCExpFileNotFound();
		return NULL;
	}
		
	// Read in the length in bytes from the header to the pixel data
	fread(&length, sizeof(byte), 1, pFile);
	
	// Jump over one byte
	fseek(pFile,1,SEEK_CUR); 

	// Read in the imageType (RLE, RGB, etc...)
	fread(&imageType, sizeof(byte), 1, pFile);
	
	// Skip past general information we don't care about
	fseek(pFile, 9, SEEK_CUR); 

	// Read the width, height and bits per pixel (16, 24 or 32)
	fread(&width,  sizeof(WORD), 1, pFile);
	fread(&height, sizeof(WORD), 1, pFile);
	fread(&bits,   sizeof(byte), 1, pFile);
	
	// Now we move the file pointer to the pixel data
	fseek(pFile, length + 1, SEEK_CUR); 

	// Check if the image is RLE compressed or not
	if(imageType != TGA_RLE)
	{
		// Check if the image is a 24 or 32-bit image
		if(bits == 24 || bits == 32)
		{
			// Calculate the channels (3 or 4) - (use bits >> 3 for more speed).
			// Next, we calculate the stride and allocate enough memory for the pixels.
			channels = bits / 8;
			stride = channels * width;
			m_data = new unsigned char[stride * height];

			// Load in all the pixel data line by line
			for(int y = 0; y < height; y++)
			{
				// Store a pointer to the current line of pixels
				unsigned char *pLine = &(m_data[stride * y]);

				// Read in the current line of pixels
				fread(pLine, stride, 1, pFile);
			
				// Go through all of the pixels and swap the B and R values since TGA
				// files are stored as BGR instead of RGB (or use GL_BGR_EXT verses GL_RGB)
				for(i = 0; i < stride; i += channels)
				{
					int temp     = pLine[i];
					pLine[i]     = pLine[i + 2];
					pLine[i + 2] = temp;
				}
			}
		}
		// Check if the image is a 16 bit image (RGB stored in 1 unsigned short)
		else if(bits == 16)
		{
			unsigned short pixels = 0;
			int r=0, g=0, b=0;

			// Since we convert 16-bit images to 24 bit, we hardcode the channels to 3.
			// We then calculate the stride and allocate memory for the pixels.
			channels = 3;
			stride = channels * width;
			m_data = new unsigned char[stride * height];

			// Load in all the pixel data pixel by pixel
			for(int i = 0; i < width*height; i++)
			{
				// Read in the current pixel
				fread(&pixels, sizeof(unsigned short), 1, pFile);
				
				// To convert a 16-bit pixel into an R, G, B, we need to
				// do some masking and such to isolate each color value.
				// 0x1f = 11111 in binary, so since 5 bits are reserved in
				// each unsigned short for the R, G and B, we bit shift and mask
				// to find each value.  We then bit shift up by 3 to get the full color.
				b = (pixels & 0x1f) << 3;
				g = ((pixels >> 5) & 0x1f) << 3;
				r = ((pixels >> 10) & 0x1f) << 3;
				
				// This essentially assigns the color to our array and swaps the
				// B and R values at the same time.
				m_data[i * 3 + 0] = r;
				m_data[i * 3 + 1] = g;
				m_data[i * 3 + 2] = b;
			}
		}	
		// Else return a NULL for a bad or unsupported pixel format
		else
			return NULL;
	}
	// Else, it must be Run-Length Encoded (RLE)
	else
	{
		// Create some variables to hold the rleID, current colors read, channels, & stride.
		byte rleID = 0;
		int colorsRead = 0;
		channels = bits / 8;
		stride = channels * width;

		// Next we want to allocate the memory for the pixels and create an array,
		// depending on the channel count, to read in for each pixel.
		m_data = new unsigned char[stride * height];
		byte *pColors = new byte [channels];

		// Load in all the pixel data
		while(i < width*height)
		{
			// Read in the current color count + 1
			fread(&rleID, sizeof(byte), 1, pFile);
			
			// Check if we don't have an encoded string of colors
			if(rleID < 128)
			{
				// Increase the count by 1
				rleID++;

				// Go through and read all the unique colors found
				while(rleID)
				{
					// Read in the current color
					fread(pColors, sizeof(byte) * channels, 1, pFile);

					// Store the current pixel in our image array
					m_data[colorsRead + 0] = pColors[2];
					m_data[colorsRead + 1] = pColors[1];
					m_data[colorsRead + 2] = pColors[0];

					// If we have a 4 channel 32-bit image, assign one more for the alpha
					if(bits == 32)
						m_data[colorsRead + 3] = pColors[3];

					// Increase the current pixels read, decrease the amount
					// of pixels left, and increase the starting index for the next pixel.
					i++;
					rleID--;
					colorsRead += channels;
				}
			}
			// Else, let's read in a string of the same character
			else
			{
				// Minus the 128 ID + 1 (127) to get the color count that needs to be read
				rleID -= 127;

				// Read in the current color, which is the same for a while
				fread(pColors, sizeof(byte) * channels, 1, pFile);

				// Go and read as many pixels as are the same
				while(rleID)
				{
					// Assign the current pixel to the current index in our pixel array
					m_data[colorsRead + 0] = pColors[2];
					m_data[colorsRead + 1] = pColors[1];
					m_data[colorsRead + 2] = pColors[0];

					// If we have a 4 channel 32-bit image, assign one more for the alpha
					if(bits == 32)
						m_data[colorsRead + 3] = pColors[3];

					// Increase the current pixels read, decrease the amount
					// of pixels left, and increase the starting index for the next pixel.
					i++;
					rleID--;
					colorsRead += channels;
				}
				
			}
				
		}
	}

	// Close the file pointer that opened the file
	fclose(pFile);

	// Fill in our tImageTGA structure to pass back
	m_channels = channels;
	m_sizeX    = width;
	m_sizeY    = height;
	m_TextureType = TGA;
	return true;
UnGuard
}

bool ExCImageLoader::LoadBMP(std::string strFileName)
{
Guard(bool ExCImageLoader::LoadBMP(std::string strFileName))
	strFileName=strFileName+".bmp";
	return LoadBMP(strFileName.data());
UnGuard
}

bool ExCImageLoader::LoadPCX(std::string strFileName)
{
Guard(bool ExCImageLoader::LoadPCX(std::string strFileName))
	 PCXHEADER texInfo;            // header of texture
     //texture_t *thisTexture;       // the texture
     unsigned char *unscaledData;// used to calculate pcx
     int i;                             // index counter
     int j;                             // index counter
     int width;                         // width of texture
     int height;                        // height of texture


     // load the PCX file into the texture struct
     m_data=LoadPCXFile(strFileName, &texInfo);
     if (m_data == NULL)
     {
          free(m_data);
		  throw ExCExpNullPointer();
		  return false;
     }

     // store the texture information
     m_palette = texInfo.palette;
     m_sizeX = texInfo.xMax - texInfo.xMin + 1;
     m_sizeY = texInfo.yMax - texInfo.yMin + 1;
     
     // allocate memory for the unscaled data
     unscaledData = (unsigned char*)malloc(m_sizeX*m_sizeY*4);

     // store the unscaled data via the palette
     for (j = 0; j < m_sizeY; j++) 
     {
          for (i = 0; i < m_sizeX; i++) 
          {
               unscaledData[4*(j*m_sizeX+i)+0] = (unsigned char)m_palette[3*m_data[j*m_sizeX+i]+0];
               unscaledData[4*(j*m_sizeX+i)+1] = (unsigned char)m_palette[3*m_data[j*m_sizeX+i]+1];
               unscaledData[4*(j*m_sizeX+i)+2] = (unsigned char)m_palette[3*m_data[j*m_sizeX+i]+2];
               unscaledData[4*(j*m_sizeX+i)+3] = (unsigned char)255;
          }
     }

     // find width and height's nearest greater power of 2
     width = m_sizeX;
     height = m_sizeY;

     // find width's
     i = 0;
     while (width)
     {
          width /= 2;
          i++;
     }
     m_scaledHeight = (long)pow(2, i-1);

     // find height's
     i = 0;
     while (height)
     {
          height /= 2;
          i++;
     }
	 m_scaledWidth = (long)pow(2, i-1);

     // clear the texture data
     if (m_data != NULL)
     {
          free(m_data);
          m_data = NULL;
     }

     // reallocate memory for the texture data
     m_data = (unsigned char*)malloc(m_scaledWidth*m_scaledHeight*4);
     
     // use the GL utility library to scale the texture to the unscaled dimensions
     gluScaleImage (GL_RGBA, m_sizeX, m_sizeY, GL_UNSIGNED_BYTE, unscaledData, m_scaledWidth, m_scaledHeight, GL_UNSIGNED_BYTE, m_data);

	return true;
UnGuard
}

bool ExCImageLoader::LoadBMP(const char *strFileName)
{
Guard(bool ExCImageLoader::LoadBMP(const char *strFileName))
	//---------------------------------------------
	FILE *file;
	unsigned long size;                 // size of the image in uchars.
	unsigned long i;                    // standard counter.
	unsigned short int planes;          // number of planes in image (must be 1) 
	unsigned short int channels;        // number of bits per pixel (must be 24)
	char temp;                          // temporary color storage for bgr-rgb conversion.

	// make sure the file is there.
	if ((file = fopen(strFileName, "rb"))==NULL)
	{
		printf("ExCImageLoader::LoadBMP ==>File Not Found : %s\n",strFileName);
		throw ExCExpFileNotFound();
		return false;
	}
#ifdef UNIX_SRC
	unsigned short int is_bmp;
	if (! fread (&is_bmp, sizeof (short int), 1, file))
	{
		printf("cannot read %s.\n", strFileName);
		return false;
	}
	
	/* check if file is a bitmap */
	if (is_bmp != 19778) 
	{
		printf("%s is not a valid bmp file.\n", strFileName);
		return false;
	}
	
	fseek (file, 8, SEEK_CUR);
	/* get the position of the actual bitmap data */
	long int bfOffBits;
	if (! fread (&bfOffBits, sizeof (long int), 1, file)) 
	{
		printf("Error reading %s.\n", strFileName);
		return false;
	}
	/*sprintf(buffer,"Data at offset: %ld.", bfOffBits);
	WriteToConsol(buffer);*/
	
	// seek through the bmp header, up to the width/height:
	fseek(file, 4, SEEK_CUR);
#else
	fseek(file, 18, SEEK_SET);
#endif
	// read the width
	if ((i = fread(&m_sizeX, 4, 1, file)) != 1) 
	{
		printf("Error reading width from %s.\n", strFileName);
		return false;
	}
			
	// read the height 
	if ((i = fread(&m_sizeY, 4, 1, file)) != 1) 
	{
		printf("Error reading height from %s.\n", strFileName);
		return false;
	}
	
	
	// calculate the size (assuming 24 bits or 3 uchars per pixel).
	size = m_sizeX * m_sizeY * 3;

	// read the planes
	if ((fread(&planes, 2, 1, file)) != 1)
	{
		printf("Error reading planes from %s.\n", strFileName);
		return false;
	}

	if (planes != 1) 
	{
		printf("Planes from %s is not 1: %u.\n", strFileName, planes);
		return false;
	}

	// read the channels
	if ((i = fread(&channels, 2, 1, file)) != 1) 
	{
		printf("Error reading channels from %s.\n", strFileName);
		return false;
	}
	if (channels != 24) 
	{
		printf("channels from %s is not 24: %u\n", strFileName, channels);
		return false;
	}
	
	// seek past the rest of the bitmap header.
	fseek(file, 24, SEEK_CUR);
	// read the data. 
	m_data = new unsigned char[size];
	//char *foo = new char[size];
	//m_data = foo;
	
	if (m_data == NULL) 
	{
		printf("Error allocating memory for color-corrected image data");
		return false;	
	}

	if ((i = fread(m_data, size, 1, file)) != 1)
	{
		printf("Error reading image data from %s.\n", strFileName);
		return false;
	}

	for (i=0;i<size;i+=3) 
	{ 
		// reverse all of the colors. (bgr -> rgb)
		temp = m_data[i];
		m_data[i] = m_data[i+2];
		m_data[i+2] = temp;
	}
	//---------------------------------------------
	m_type=GL_RGB;
	m_channels=3;
	fclose(file);
	return true;
UnGuard
}

unsigned char * ExCImageLoader::LoadPCXFile(std::string filename, PCXHEADER *pcxHeader)
{
Guard(unsigned char * ExCImageLoader::LoadPCXFile(std::string filename, PCXHEADER *pcxHeader)) 
	int idx = 0;                  // counter index
     int c;                             // used to retrieve a char from the file
     int i;                             // counter index
     int numRepeat;      
     FILE *filePtr;                // file handle
     int width;                         // pcx width
     int height;                        // pcx height
	 unsigned char *pixelData;     // pcx image data
     unsigned char *paletteData;   // pcx palette data

     filename=filename+".pcx";
	 // open PCX file
     filePtr = fopen(filename.data(), "rb");
	 if (filePtr == NULL)
	 {
		throw ExCExpFileNotFound();
		return NULL;
	 }
     // retrieve first character; should be equal to 10
     c = getc(filePtr);
     if (c != 10)
     {
          fclose(filePtr);
          return NULL;
     }
     // retrieve next character; should be equal to 5
     c = getc(filePtr);
     if (c != 5)
     {
          fclose(filePtr);
          return NULL;
     }
     // reposition file pointer to beginning of file
     rewind(filePtr);

     // read 4 characters of data to skip
     fgetc(filePtr);
     fgetc(filePtr);
     fgetc(filePtr);
     fgetc(filePtr);

     // retrieve leftmost x value of PCX
     pcxHeader->xMin = fgetc(filePtr);       // loword
     pcxHeader->xMin |= fgetc(filePtr) << 8; // hiword

     // retrieve bottom-most y value of PCX
     pcxHeader->yMin = fgetc(filePtr);       // loword
     pcxHeader->yMin |= fgetc(filePtr) << 8; // hiword

     // retrieve rightmost x value of PCX
     pcxHeader->xMax = fgetc(filePtr);       // loword
     pcxHeader->xMax |= fgetc(filePtr) << 8; // hiword

     // retrieve topmost y value of PCX
     pcxHeader->yMax = fgetc(filePtr);       // loword
     pcxHeader->yMax |= fgetc(filePtr) << 8; // hiword

     // calculate the width and height of the PCX
     width = pcxHeader->xMax - pcxHeader->xMin + 1;
     height = pcxHeader->yMax - pcxHeader->yMin + 1;

     // allocate memory for PCX image data
     pixelData = (unsigned char*)malloc(width*height);

     // set file pointer to 128th byte of file, where the PCX image data starts
     fseek(filePtr, 128, SEEK_SET);
     
     // decode the pixel data and store
     while (idx < (width*height))
     {
          c = getc(filePtr);
          if (c > 0xbf)
          {
               numRepeat = 0x3f & c;
               c = getc(filePtr);

               for (i = 0; i < numRepeat; i++)
               {
                    pixelData[idx++] = c;
               }
          }
          else
               pixelData[idx++] = c;

          fflush(stdout);
     }

     // allocate memory for the PCX image palette
     paletteData = (unsigned char*)malloc(768);

     // palette is the last 769 bytes of the PCX file
     fseek(filePtr, -769, SEEK_END);

     // verify palette; first character should be 12
     c = getc(filePtr);
     if (c != 12)
     {
          fclose(filePtr);
          return NULL;
     }
     // read and store all of palette
     for (i = 0; i < 768; i++)
     {
          c = getc(filePtr);
          paletteData[i] = c;
     }

     // close file and store palette in header
     fclose(filePtr);
     pcxHeader->palette = paletteData;

	 // return the pixel image data
	 return pixelData;
UnGuard
}
//----------------------------------------------------------------------------------------------------------
bool ExCImageLoader::SaveImage(std::string FileName,int width,int height)
{
	Guard(bool ExCImageLoader::SaveImage(std::string FileName,int width,int height))
	m_TextureType=FindTextureType(FileName);
	
	unsigned char * imageData;
	imageData= (unsigned char*) malloc(width*height*3);
	memset(imageData,255, width* height* 3);

	glReadBuffer(GL_FRONT);
	glReadPixels(0, 0, width- 1, height- 1, GL_RGB, GL_UNSIGNED_BYTE, imageData);


	switch(m_TextureType)
	{
	case BMP:return SaveBMP(FileName,width,height,imageData);
	case TGA:return SaveTGA(FileName,width,height,imageData);
	case PCX:return SavePCX(FileName,width,height,imageData);
	case JPG:return SaveJPG(FileName,width,height,imageData);
	case RGB:return SaveRGB(FileName,width,height,imageData);
	case RAW:return SaveRAW(FileName,width,height,imageData);
	case PPM:return SavePPM(FileName,width,height,imageData);
	case UNKNOWN:return false;
	default:return false;
	}
	UnGuard
}

bool ExCImageLoader::SaveTGA(std::string strFileName,int width,int height,unsigned char * ImageData)
{
Guard(bool ExCImageLoader::SaveTGA(std::string strFileName,int width,int height,unsigned char * ImageData))
	FILE *pFile;               // The file pointer.
	unsigned char uselessChar=0; // used for useless char.
	short int uselessInt=0;      // used for useless int.
	unsigned char imageType=2;   // Type of image we are saving.
	int index=0;                 // used with the for loop.
	unsigned char bits=24;    // Bit depth.
	int colorMode=3;
	long Size=width * height * colorMode;                // Size of the picture.
	// Open file
	if(pFile= fopen(strFileName.data(), "wb"))
	{
		fwrite(&uselessChar, sizeof(unsigned char), 1, pFile);// Write useless data.
		fwrite(&uselessChar, sizeof(unsigned char), 1, pFile);// Write useless data.
		fwrite(&imageType, sizeof(unsigned char), 1, pFile);// Write image type.
		fwrite(&uselessInt, sizeof(short int), 1, pFile);// Write useless data.
		fwrite(&uselessInt, sizeof(short int), 1, pFile);// Write useless data.
		fwrite(&uselessChar, sizeof(unsigned char), 1, pFile);// Write useless data.
		fwrite(&uselessInt, sizeof(short int), 1, pFile);// Write useless data.
		fwrite(&uselessInt, sizeof(short int), 1, pFile);// Write useless data.
		fwrite(&width, sizeof(short int), 1, pFile);// Write width.
		fwrite(&height, sizeof(short int), 1, pFile);// Write height.
		fwrite(&bits, sizeof(unsigned char), 1, pFile);//Write bits
		fwrite(&uselessChar, sizeof(unsigned char), 1, pFile);// Write useless data.
		for(index = 0; index < Size; index += colorMode)// Transform data RGB to BGR.
			ImageData[index]^= ImageData[index + 2]^=ImageData[index]^=ImageData[index + 2];
		fwrite(ImageData, sizeof(unsigned char), Size, pFile);//Write image data.
		fclose(pFile); 
		return true;
	}
	fclose(pFile);
	return false; 
UnGuard
}

bool ExCImageLoader::SaveBMP(std::string strFileName,int width,int height,unsigned char * ImageData)
{
	Guard(bool ExCImageLoader::SaveBMP(std::string strFileName,int width,int height,unsigned char * ImageData))
	return false;
	UnGuard
}
bool ExCImageLoader::SavePCX(std::string strFileName,int width,int height,unsigned char * ImageData)
{
	Guard(bool ExCImageLoader::SavePCX(std::string strFileName,int width,int height,unsigned char * ImageData))
		return false;
	UnGuard
}

bool ExCImageLoader::SaveJPG(std::string strFileName,int width,int height,unsigned char * ImageData)
{
	Guard(bool ExCImageLoader::SaveJPG(std::string strFileName,int width,int height,unsigned char * ImageData))
		return false;
	UnGuard
}

bool ExCImageLoader::SaveRGB(std::string strFileName,int width,int height,unsigned char * ImageData)
{
	Guard(bool ExCImageLoader::SaveRGB(std::string strFileName,int width,int height,unsigned char * ImageData))
		return false;
	UnGuard
}

bool ExCImageLoader::SaveRAW(std::string strFileName,int width,int height,unsigned char * ImageData)
{
	Guard(bool ExCImageLoader::SaveRAW(std::string strFileName,int width,int height,unsigned char * ImageData))
		return false;
	UnGuard
}

bool ExCImageLoader::SavePPM(std::string strFileName,int width,int height,unsigned char * ImageData)
{
	Guard(bool ExCImageLoader::SavePPM(std::string strFileName,int width,int height,unsigned char * ImageData))
		return false;
	UnGuard
}