/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////*****************************************************************************************************////////////////
///////////////** 																									**///////////////
//////////////**								~ Zoo Engine (Moteur 3D pour SCOL) ~								 **//////////////
/////////////**											  ~ version 1.0 ~											  **/////////////
/////////////**																										  **/////////////
//////////////**										par Pacôme DANHIEZ		  									 **//////////////
///////////////** 																									**///////////////
////////////////*****************************************************************************************************////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///																																  ///
///		FICHIER :	ZooTexture.cpp																								  ///
///																																  ///
///		NATURE	:	Définition des classes de texture et matériau - Méthodes relatives au chargement et à la gestion -			  ///
///																																  ///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////




#include	"..\Datas\zootexture.h"


#include "..\Loaders\JPEG\LoaderJpeg.h"
#include "../scol/colors.h"



///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// ZTexture Class
///
///		- Classe des textures : Image, filtre, et taille
///		- Méthodes pour le set des composantes et pour le chargement d'un BMP ou JPG
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////
/// Constructor					 										///
///////////////////////////////////////////////////////////////////////////
ZTexture::ZTexture(bool accel) : ZData()
{
	type	= TEX_TYPE_ID;

	Image		= NULL;
	ImageModif	= NULL;
	bitmap24	= NULL;
	
	Width = Height = 0;

	C = X = Y = A = R = S = false;
	
	modified  = true;
	activated = false;
	renamed	  = true;

	transpR = 0;
	transpG = 0;
	transpB = 0;
	rate	= 0;
	value	= 0;

	ID_created	= false;
	
	filter	= -1;

	accelerated = accel;
}



///////////////////////////////////////////////////////////////////////////
///		Destructor				 										///
///////////////////////////////////////////////////////////////////////////
ZTexture::~ZTexture()
{
	if(Image!=NULL)				free(Image);
	if(ImageModif!=NULL)		free(ImageModif);
	Image = ImageModif = NULL;

	if(ID_created && accelerated)
	{
		glDeleteTextures(1, &texID);
		ID_created = false;
	}
}



///////////////////////////////////////////////////////////////////////////////////////////////
///		SetTextureFilter																	///
///////////////////////////////////////////////////////////////////////////////////////////////
void ZTexture::SetTextureFilter(int newfilter)
{
	if( (newfilter>=0) && (newfilter<=2) )
	{
		if(activated)
		{
			filter = newfilter;

			PutGLparams();
			if(ImageModif)		free(ImageModif);
			ImageModif = (unsigned char *) malloc(Width * Height * 4);
			glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, ImageModif);

			SetupTexture();
		}
		else
			filter = newfilter;
	}
}



///////////////////////////////////////////////////////////////////////////////////////////////
///		LoadTexture																			///
///////////////////////////////////////////////////////////////////////////////////////////////
bool ZTexture::LoadTexture(char *filename)
{
/*
	int i=0;

	while(filename[i] != '.')	i++;

	if ( ((filename[i+1]=='b') || (filename[i+1]=='B')) && 
		 ((filename[i+2]=='m') || (filename[i+2]=='M')) &&
		 ((filename[i+3]=='p') || (filename[i+3]=='P'))		)
	{
		if (LoadBMPTexture(filename) == false)		{	activated = false;	return false;	}
	}
	else
	if ( ((filename[i+1]=='j') || (filename[i+1]=='J')) &&
		 ((filename[i+2]=='p') || (filename[i+2]=='P')) &&
		 ((filename[i+3]=='g') || (filename[i+3]=='G'))		)
	{
		if (LoadJPGTexture(filename) == false)		{	activated = false;	return false;	}
	}
	else
	if ( ((filename[i+1]=='p') || (filename[i+1]=='P')) &&
		 ((filename[i+2]=='n') || (filename[i+2]=='N')) &&
		 ((filename[i+3]=='g') || (filename[i+3]=='G'))		)
	{
		if (LoadPNGTexture(filename) == false)		{	activated = false;	return false;	}
	}
	else
		return false;

	// declare the texture as ACTIVATED
	activated = true;
*/
	if(LoadJPGTexture(filename)==true)
	{
		activated = true;
		return StretchImage();
	}

	if(LoadPNGTexture(filename)==true)
	{
		activated = true;
		return StretchImage();
	}

	if(LoadBMPTexture(filename)==true)
	{
		activated = true;
		return StretchImage();
	}


	activated = false;
	return false;
}



///////////////////////////////////////////////////////////////////////////////////////////////
///		StretchImage																		///
///////////////////////////////////////////////////////////////////////////////////////////////
bool ZTexture::StretchImage()
{
	// ------ Stretch de la texture ------
	int		i, j, in, jn, x, y, ybase, yl;
	unsigned char *bufn;

	if(!Image)		{	activated = false;	return false;	}

	i = Width;
	j = Height;

	if(accelerated)
	{
		if(		( (i==512)||(i==256)||(i==128)||(i==64)||(i==32) )
			&&  ( (j==512)||(j==256)||(j==128)||(j==64)||(j==32) )	)		return true;
	}
	else
	{
		if(    ((i==256) && (j==256) )
			|| ((i==512) && (j==256) )
			|| ((i==256) && (j==512) )
			|| ((i==512) && (j==512) )
			|| ((i==1024)&& (j==512) )
			|| ((i==512) && (j==1024))
			|| ((i==1024)&& (j==1024))
			|| ((i==256) && (j==128) )
			|| ((i==128) && (j==256) )
			|| ((i==128) && (j==128) )
			|| ((i==128) && (j==64)  )
			|| ((i==64)  && (j==128) )
			|| ((i==64)  && (j==64)  )
			|| ((i==64)  && (j==32)  )
			|| ((i==32)  && (j==64)  )
			|| ((i==32)  && (j==32)  ) )	return true;
	}

	if(i > j)
	{
			 if (i<=32)		in = 32;
		else if (i<=64)		in = 64;
		else if (i<=128)	in = 128;
		else if (i<=256)	in = 256;
		else				in = 512;

		if(i > j+j)			jn = in>>1;
		else				jn = in;
	}
	else
	{
			 if(j<=32)		jn = 32;
		else if(j<=64)		jn = 64;
		else if(j<=128)		jn = 128;
		else if(j<=256)		jn = 256;
		else				jn = 512;

		if(j > i+i)			in = jn>>1;
		else				in = jn;
	}

	bufn = (unsigned char *) malloc(in*jn*4);
	if(bufn==NULL)								{	activated = false;	return false;	}

	for(y=0; y<jn; y++)
	{
		ybase = y*in;
		yl	  = y*j/jn;
		yl	 *= i;

		for(x=0; x<in; x++)
		{
			bufn[ (ybase+x)*4+0 ] = Image[ (yl+x*i/in)*4+0 ];
			bufn[ (ybase+x)*4+1 ] = Image[ (yl+x*i/in)*4+1 ];
			bufn[ (ybase+x)*4+2 ] = Image[ (yl+x*i/in)*4+2 ];
			bufn[ (ybase+x)*4+3 ] = Image[ (yl+x*i/in)*4+3 ];
		}
	}

	free(Image);

	Image	= (unsigned char *)bufn;
	Width	= in;
	Height	= jn;

	return true;
}



///////////////////////////////////////////////////////////////////////////////////////////////
///		StretchImageModif																	///
///////////////////////////////////////////////////////////////////////////////////////////////
bool ZTexture::StretchImageModif()
{
	// ------ Stretch de la texture ------
	int		i, j, in, jn, x, y, ybase, yl;
	unsigned char *bufn;

	if(!ImageModif)		{	activated = false;	return false;	}

	i = Width;
	j = Height;

	if(    ((i==256) && (j==256) )
		|| ((i==512) && (j==256) )
		|| ((i==256) && (j==512) )
		|| ((i==512) && (j==512) )
		|| ((i==1024)&& (j==512) )
		|| ((i==512) && (j==1024))
		|| ((i==1024)&& (j==1024))
		|| ((i==256) && (j==128) )
		|| ((i==128) && (j==256) )
		|| ((i==128) && (j==128) )
		|| ((i==128) && (j==64)  )
		|| ((i==64)  && (j==128) )
		|| ((i==64)  && (j==64)  )
		|| ((i==64)  && (j==32)  )
		|| ((i==32)  && (j==64)  )
		|| ((i==32)  && (j==32)  ) )	return true;

	if(i > j)
	{
			 if (i<=32)		in = 32;
		else if (i<=64)		in = 64;
		else if (i<=128)	in = 128;
		else if (i<=256)	in = 256;
		else				in = 512;

		if(i > j+j)			jn = in>>1;
		else				jn = in;
	}
	else
	{
			 if(j<=32)		jn = 32;
		else if(j<=64)		jn = 64;
		else if(j<=128)		jn = 128;
		else if(j<=256)		jn = 256;
		else				jn = 512;

		if(j > i+i)			in = jn>>1;
		else				in = jn;
	}

	bufn = (unsigned char *) malloc(in*jn*4);
	if(bufn==NULL)								{	activated = false;	return false;	}

	for(y=0; y<jn; y++)
	{
		ybase = y*in;
		yl	  = y*j/jn;
		yl	 *= i;

		for(x=0; x<in; x++)
		{
			bufn[ (ybase+x)*4+0 ] = ImageModif[ (yl+x*i/in)*4+0 ];
			bufn[ (ybase+x)*4+1 ] = ImageModif[ (yl+x*i/in)*4+1 ];
			bufn[ (ybase+x)*4+2 ] = ImageModif[ (yl+x*i/in)*4+2 ];
			bufn[ (ybase+x)*4+3 ] = ImageModif[ (yl+x*i/in)*4+3 ];
		}
	}

	free(ImageModif);

	ImageModif	= (unsigned char *)bufn;
	Width	= in;
	Height	= jn;

	return true;
}




///////////////////////////////////////////////////////////////////////////////////////////////
///		LoadBitmapTexture																	///
///////////////////////////////////////////////////////////////////////////////////////////////
bool ZTexture::LoadBMPTexture(char *filename)//, bool transpColor, unsigned char Red, unsigned char Green, unsigned char Blue, unsigned char tolerance)
{
	FILE				* File;
	BITMAPFILEHEADER	FileHeader;
	BITMAPINFOHEADER	InfoHeader;
	DWORD				Type;
	int					i, j, off=0;

//	_asm{int 3};

	if ((File = fopen(filename, "rb"))==NULL)		return false;
	
	// test de validité du fichier
	char test[1200];
	fread(test,1,0x36,File);
	if(test[0]!='B' || test[1]!='M')
	{
		fclose(File);
		return false;
	}
	fseek(File, 0, SEEK_SET);

	// read the header and type, then seek to the next position
	fread(&FileHeader, sizeof(FileHeader), 1, File);
	fread(&Type, sizeof(Type), 1, File);
	fseek(File, sizeof(FileHeader), SEEK_SET);

	// read the infoheader
	fread(&InfoHeader, sizeof(InfoHeader), 1, File);


	// set our texture width and height from what is read in the file
	Width	= InfoHeader.biWidth;
	Height	= InfoHeader.biHeight;

	if(InfoHeader.biBitCount == 16)
	{
		if(Image!=NULL)		free(Image);
		Image	= (unsigned char *) malloc(Width * Height * 4);
		memset(Image, 0, Width * Height * 4);

		int k;
		int testX = (Width*2)%4;
		if(testX!=0)		testX = 4-testX;
		
		if(InfoHeader.biCompression==BI_RGB)
		{
			unsigned short	maskB=0x001F, maskG=0x03E0, maskR=0x7C00;
			unsigned short	coul;

			for (j=0; j < InfoHeader.biHeight; j++)
			{
				for (i=0; i < InfoHeader.biWidth; i++)
				{
					fread(&coul, sizeof(coul), 1, File);

					Image[off+0] = (coul&maskR)>>7;
					Image[off+1] = (coul&maskG)>>2;
					Image[off+2] = (coul&maskB)<<3;
					Image[off+3] = 255;

					off += 4;
				}
				for(k=0; k<testX; k++)		fgetc(File);
			}
		}
		else
		{
			fclose(File);
			return false;
		}
	}
	else
	if(InfoHeader.biBitCount == 24)
	{
		if(Image!=NULL)		free(Image);
		Image	= (unsigned char *) malloc(Width * Height * 4);
		memset(Image, 0, Width * Height * 4);
		RGBTRIPLE			rgb;

		int testX = (Width*3)%4;
		if(testX!=0)		testX = 4-testX;

		int k;

		for (j=0; j < Height; j++)
		{
			for (i=0; i < Width; i++)
			{
				// load the r g and b values from the file into an RGBTRIPLE structure
				fread(&rgb, sizeof(rgb), 1, File);

				Image[off+0] = rgb.rgbtRed;
				Image[off+1] = rgb.rgbtGreen;
				Image[off+2] = rgb.rgbtBlue;
				Image[off+3] = 255;
				off += 4;
			}

			for(k=0; k<testX; k++)		fgetc(File);
		}
	}
	else
	if(InfoHeader.biBitCount == 32)
	{
		if(Image!=NULL)		free(Image);
		Image	= (unsigned char *) malloc(Width * Height * 4);
		memset(Image, 0, Width * Height * 4);
		RGBQUAD			rgba;

		for (j=0; j < InfoHeader.biHeight; j++)
		{
			for (i=0; i < InfoHeader.biWidth; i++)
			{
				// load the r g and b values from the file into an RGBTRIPLE structure
				fread(&rgba, sizeof(rgba), 1, File);

				Image[off+0] = rgba.rgbRed;
				Image[off+1] = rgba.rgbGreen;
				Image[off+2] = rgba.rgbBlue;
				Image[off+3] = rgba.rgbReserved;

				off += 4;
			}
		}
	}
	else
	if(InfoHeader.biBitCount == 8)
	{
		if(Image!=NULL)		free(Image);
		Image	= (unsigned char *) malloc(Width * Height * 4);
		memset(Image, 0, Width * Height * 4);

		fseek(File, 54, SEEK_SET);

		RGBQUAD			rgb[256];
		for (i=0; i < 256; i++)			fread(&(rgb[i]), sizeof(rgb[i]), 1, File);

		fseek(File, 1078, SEEK_SET);
		unsigned char	coul;

		transpR = rgb[0].rgbRed;
		transpG = rgb[0].rgbGreen;
		transpB = rgb[0].rgbBlue;

		int k;
		int testX = (Width)%4;
		if(testX!=0)		testX = 4-testX;

		for (j=0; j < InfoHeader.biHeight; j++)
		{
			for (i=0; i < InfoHeader.biWidth; i++)
			{
				// load the r g and b values from the file into an RGBTRIPLE structure
				fread(&coul, 1, 1, File);

				Image[off+0] = rgb[coul].rgbRed;
				Image[off+1] = rgb[coul].rgbGreen;
				Image[off+2] = rgb[coul].rgbBlue;

				if(coul)		Image[off+3] = 255;
				else			Image[off+3] = 0;

				off += 4;
			}
			for(k=0; k<testX; k++)		fgetc(File);
		}
	}

	fclose(File);

	return true;
}



int GetHEXA(const string &c, int pos, int size)
{
	int	a,k,i,n;
	k=0;
	for(i=pos; i<pos+size; i++)
	{
		a = c[i];
		if ((a>='0')&&(a<='9'))			n = a-'0';
		else if ((a>='A')&&(a<='F'))	n = 10+a-'A';
		else if ((a>='a')&&(a<='f'))	n = 10+a-'a';
		else							n = 0;
		k = (k<<4) + n;
	}
	
	return k;
}


int RGB2HSV(unsigned char R, unsigned char G, unsigned char B, float *rh, float *rs, float *rv)
{
	int		max, min;
	float	h, s, v, delta;

	if(R>G)			max = R;
	else			max = G;
	if(B>max)		max = B;

	if(R<G)			min = R; 
	else			min = G;
	if(B<min)		min = B;
	
	v = max;
	v/= 255;

	if(max)
	{
		s = max-min;
		s/= max;
	}
	else s=0;

	if(s==0)	h=0;
	else
	{
		delta = max-min;
		if(R==max)			h = (G-B)/delta;
		else if(G==max)		h = 2+(B-R)/delta;
		else				h = 4+(R-G)/delta;
		h *= 60;
		if(h<0)				h += 360;
	}
	
	*rh=h; 
	*rs=s; 
	*rv=v;

	return 0;
}


void HSV2RGB(float h, float s, float v, unsigned char *R, unsigned char *G, unsigned char *B)
{
	int		i;
	float	f,p,q,t;
		
	v *= 255.0f;
	if(s==0.0f)		*R = *G = *B = v;
	else
	{
		while(h>=360.0f)		h -= 360.0f;
		while(h<0.0f)			h += 360.0f;
		h/=60.0f;
		i = floor(h);
		f = h-(float)i;
		p = v*(1.-s);
		q = v*(1.-s*f);
		t = v*(1.-s*(1.-f));
		
		switch(i)	
		{
			case 0:
					*R=v; *G=t; *B=p;
					break;
			case 1:
					*R=q; *G=v; *B=p;
					break;
			case 2:
					*R=p; *G=v; *B=t;
					break;
			case 3:
					*R=p; *G=q; *B=v;
					break;
			case 4:
					*R=t; *G=p; *B=v;
					break;
			case 5:
					*R=v; *G=p; *B=q;
					break;
		}
	}
}


///////////////////////////////////////////////////////////////////////////////////////////////
///		CreateModifiedImg																	///
///////////////////////////////////////////////////////////////////////////////////////////////
bool ZTexture::CreateModifiedImg()
{
	if(Image==NULL)		return false;

	if(ImageModif==NULL)	ImageModif	= (unsigned char *) malloc(Width * Height * 4);
	memcpy(ImageModif, Image, Width*Height*4);

	int i=0, size=name.size();
	int	colR, colG, colB, coef;

	C = X = Y = A = R = S = false;

	if(size && name[i]=='%')
	{
		i++;

		while(i<size && name[i]!='%')
		{
			if(name[i]=='C' && (size-i>8) )
			{
				colB = GetHEXA(name, i+1, 2);		colG = GetHEXA(name, i+3, 2);
				colR = GetHEXA(name, i+5, 2);		coef = GetHEXA(name, i+7, 2);

				for(int off=0; off<Width*Height*4; off+=4)
				{
					ImageModif[off+0] = ((ImageModif[off+0]*(256-coef))>>8) + ((colR*coef)>>8);
					ImageModif[off+1] = ((ImageModif[off+1]*(256-coef))>>8) + ((colG*coef)>>8);
					ImageModif[off+2] = ((ImageModif[off+2]*(256-coef))>>8) + ((colB*coef)>>8);
				}
				i += 9;
			}
			else if(name[i]=='A' && (size-i>8) )
			{
				colB = GetHEXA(name, i+1, 2);		colG = GetHEXA(name, i+3, 2);
				colR = GetHEXA(name, i+5, 2);		coef = GetHEXA(name, i+7, 2);

				transpR = colR;		
				transpG = colG;		
				transpB = colB;		
				rate	= coef;
				
				A = true;

				coef *= 3;

				for(int off=0; off<Width*Height*4; off+=4)
				{
					if( abs(ImageModif[off+0]-colR)+abs(colG-ImageModif[off+1])+abs(ImageModif[off+2]-colB) < coef )
					{
						if(accelerated)	ImageModif[off+0] = ImageModif[off+1] = ImageModif[off+2] = 0;
						else
						{
							ImageModif[off+0] = colR;
							ImageModif[off+1] = colG;
							ImageModif[off+2] = colB;
						}
						ImageModif[off+3] = 0;
					}
				}
				i+=9;
			}
			else if(name[i]=='X')
			{
				char tmpCol;




				for(int off=0; off<Width*Height*4; off+=4)
				{
					tmpCol = ImageModif[off+0];
					ImageModif[off+0] = ImageModif[off+1];
					ImageModif[off+1] = ImageModif[off+2];
					ImageModif[off+2] = tmpCol;
				}
				i++;
			}
			else if(name[i]=='Y')
			{
				char tmpCol;



				for(int off=0; off<Width*Height*4; off+=4)
				{
					tmpCol = ImageModif[off+2];
					ImageModif[off+2] = ImageModif[off+1];
					ImageModif[off+1] = ImageModif[off+0];
					ImageModif[off+0] = tmpCol;
				}
				i++;
			}
			else if(name[i]=='R' && (size-i>4) )
			{


				int		ang = (GetHEXA(name, i+1, 4)*360)>>16;
				float	rh, rs, rv;
				for(int off=0; off<Width*Height*4; off+=4)
				{
					RGB2HSV(ImageModif[off+0], ImageModif[off+1], ImageModif[off+2], &rh,&rs,&rv);
					HSV2RGB(rh+ang, rs, rv, &ImageModif[off+0], &ImageModif[off+1], &ImageModif[off+2]);
				}
				i+=5;
			}
			else if(name[i]=='S' && (size-i>6) )
			{




				int		sat16 = GetHEXA(name, i+1, 4);
				float	sat = sat16;
				float	rh, rs, rv;

				sat /= 65536.0f;
				coef = GetHEXA(name, i+5, 2);

				for(int off=0; off<Width*Height*4; off+=4)
				{
					RGB2HSV(ImageModif[off+0], ImageModif[off+1], ImageModif[off+2], &rh,&rs,&rv);
					HSV2RGB(rh, (rs*(256-coef)+sat*coef)/256, rv, &ImageModif[off+0], &ImageModif[off+1], &ImageModif[off+2]);
				}
				i+=7;
			}
			else i++;
		}
	}

	renamed = false;			// becoz we have used the NEW flags of rendering
	free(Image);
	Image = NULL;




	return true;
}



///////////////////////////////////////////////////////////////////////////////////////////////
///		CreateModifiedImg																	///
///////////////////////////////////////////////////////////////////////////////////////////////
bool ZTexture::CreateModifiedImg_WithoutLoading_A()
{
	if(Image==NULL)		return false;

	if(ImageModif==NULL)	ImageModif	= (unsigned char *) malloc(Width * Height * 4);
	memcpy(ImageModif, Image, Width*Height*4);

	int i=0, size=name.size();
	int	colR, colG, colB, coef;

	C = X = Y = R = S = false;

	if(size && name[i]=='%')
	{
		i++;

		while(i<size && name[i]!='%')
		{
			if(name[i]=='C' && (size-i>8) )
			{
				colB = GetHEXA(name, i+1, 2);		colG = GetHEXA(name, i+3, 2);
				colR = GetHEXA(name, i+5, 2);		coef = GetHEXA(name, i+7, 2);

				for(int off=0; off<Width*Height*4; off+=4)
				{
					ImageModif[off+0] = ((ImageModif[off+0]*(256-coef))>>8) + ((colR*coef)>>8);
					ImageModif[off+1] = ((ImageModif[off+1]*(256-coef))>>8) + ((colG*coef)>>8);
					ImageModif[off+2] = ((ImageModif[off+2]*(256-coef))>>8) + ((colB*coef)>>8);
				}
				i += 9;
			}
			else if(name[i]=='A' && (size-i>8) )
			{
				i+=9;
			}
			else if(name[i]=='X')
			{
				char tmpCol;
				for(int off=0; off<Width*Height*4; off+=4)
				{
					tmpCol = ImageModif[off+0];
					ImageModif[off+0] = ImageModif[off+1];
					ImageModif[off+1] = ImageModif[off+2];
					ImageModif[off+2] = tmpCol;
				}
				i++;
			}
			else if(name[i]=='Y')
			{
				char tmpCol;
				for(int off=0; off<Width*Height*4; off+=4)
				{
					tmpCol = ImageModif[off+2];
					ImageModif[off+2] = ImageModif[off+1];
					ImageModif[off+1] = ImageModif[off+0];
					ImageModif[off+0] = tmpCol;
				}
				i++;
			}
			else if(name[i]=='R' && (size-i>4) )
			{
				int		ang = (GetHEXA(name, i+1, 4)*360)>>16;
				float	rh, rs, rv;
				for(int off=0; off<Width*Height*4; off+=4)
				{
					RGB2HSV(ImageModif[off+0], ImageModif[off+1], ImageModif[off+2], &rh,&rs,&rv);
					HSV2RGB(rh+ang, rs, rv, &ImageModif[off+0], &ImageModif[off+1], &ImageModif[off+2]);
				}
				i+=5;
			}
			else if(name[i]=='S' && (size-i>6) )
			{
				int		sat16 = GetHEXA(name, i+1, 4);
				float	sat = sat16;
				float	rh, rs, rv;

				sat /= 65536.0f;
				coef = GetHEXA(name, i+5, 2);

				for(int off=0; off<Width*Height*4; off+=4)
				{
					RGB2HSV(ImageModif[off+0], ImageModif[off+1], ImageModif[off+2], &rh,&rs,&rv);
					HSV2RGB(rh, (rs*(256-coef)+sat*coef)/256, rv, &ImageModif[off+0], &ImageModif[off+1], &ImageModif[off+2]);
				}
				i+=7;
			}
			else i++;
		}
	}

	if(A)
	{
		coef = rate*3;

		for(int off=0; off<Width*Height*4; off+=4)
		{
			if( abs(ImageModif[off+0]-transpR)+abs(transpG-ImageModif[off+1])+abs(ImageModif[off+2]-transpB) < coef )
			{
				if(accelerated)	ImageModif[off+0] = ImageModif[off+1] = ImageModif[off+2] = 0;
				else
				{
					ImageModif[off+0] = transpR;
					ImageModif[off+1] = transpG;
					ImageModif[off+2] = transpB;
				}
				ImageModif[off+3] = 0;
			}
		}
	}


	renamed = false;			// becoz we have used the NEW flags of rendering
	free(Image);
	Image = NULL;

	return true;
}



///////////////////////////////////////////////////////////////////////////////////////////////
///		SetupTexture																		///
///////////////////////////////////////////////////////////////////////////////////////////////
void ZTexture::SetupTexture()
{


	if(accelerated)
	{
		if(ID_created)
		{
			glDeleteTextures(1, &texID);
			ID_created = false;
		}

		if(ImageModif==NULL)		return;

		// tell OpenGL we want to use this texture's Id
		glGenTextures(1, &texID);
		ID_created = true;
		glBindTexture(GL_TEXTURE_2D, texID);


		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);


		if( (filter==TF_NONE)  )
		{
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		}
		else if(filter == TF_LINEAR)
		{
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		}
		else if(filter == TF_BILINEAR)
		{
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
		}
		else if(filter == TF_TRILINEAR)
		{
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
		}

		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

		glTexImage2D(GL_TEXTURE_2D, 0, 4, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, ImageModif );

		if(filter!=TF_NONE)			gluBuild2DMipmaps( GL_TEXTURE_2D, 4, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, ImageModif );

		free(ImageModif);
		ImageModif = NULL;
	}
	else
	{
	int i, im;

		//$LB
		if(bitmap24)	free(bitmap24);

		bitmap24 = (OBJBITMAP_BUFFER) malloc(Width * Height * 3);

		OBJBITMAP_BUFFER bitm = (OBJBITMAP_BUFFER)bitmap24;

		for(i=0, im=0; i< Width * Height * 3;)
		{
			bitm[i++] = ImageModif[im++];
			bitm[i++] = ImageModif[im++];
			bitm[i++] = ImageModif[im++];
			im++;
		}

		free(ImageModif);
		ImageModif = NULL;
	}
}





///////////////////////////////////////////////////////////////////////////
/// Load JPEG image														///
///////////////////////////////////////////////////////////////////////////
bool ZTexture::LoadJPGTexture(char *filename)
{
	Image = (unsigned char*) LoadJpgFromFile(filename, &Width, &Height);

	if(Image==NULL)		return false;
	else				return true;

}






///////////////////////////////////
///	The loader					///
///////////////////////////////////
bool ZTexture::LoadPNGTexture(char *filename)
{
	long	image_width, image_height;
	uch		bg_red=0, bg_green=0, bg_blue=0;
	uch		trn_red=0, trn_green=0, trn_blue=0;
	ulg		image_rowbytes;
	int		image_channels;
	uch		*image_data;

	FILE *infile = NULL;
	if((infile=fopen(filename,"rb"))==NULL)		return false;

	if( readpng_init(infile, &image_width, &image_height) != 0)
	{
		fclose(infile);
        readpng_cleanup( TRUE );
		return false;
	}

	if (readpng_get_bgcolor(&bg_red, &bg_green, &bg_blue) > 1)
	{
		fclose( infile );
        readpng_cleanup( TRUE );
		return false;
	}


	image_data = readpng_get_image( &image_channels, &image_rowbytes );
    fclose(infile);

    if (!image_data)
	{
		readpng_cleanup(TRUE);
		return false;
	}



	Width  = image_width;
	Height = image_height;

	Image  = (unsigned char *) malloc(Width * Height * 4);
	memset(Image, 0, Width * Height * 4);


    ulg i, row, lastrow;
	uch *src;

	for(lastrow = row = 0; row < Height; ++row) 
	{
        src = image_data + row * image_rowbytes;

		if(image_channels==3) 
		{
            for(i=0; i<image_width; i++) 
			{
                Image[((Height-row-1)*Width+i)*4+0] = *src++;
                Image[((Height-row-1)*Width+i)*4+1] = *src++;
                Image[((Height-row-1)*Width+i)*4+2] = *src++;
                Image[((Height-row-1)*Width+i)*4+3] = 255;
            }
        }
		else /* if ( image_channels == 4 ) */ 
		{
            for(i=0; i<image_width; i++) 
			{
                Image[((Height-row-1)*Width+i)*4+0] = *src++;
                Image[((Height-row-1)*Width+i)*4+1] = *src++;
                Image[((Height-row-1)*Width+i)*4+2] = *src++;
                Image[((Height-row-1)*Width+i)*4+3] = *src++;
            }
		}
	}
	
	
	readpng_cleanup(TRUE);

	return true;
}







///////////////////////////////////////////////////////////////////////////
/// Set the texture as the current texture in the current unit			///
///////////////////////////////////////////////////////////////////////////
void ZTexture::PutGLparams()
{
	if(ID_created)	glBindTexture(GL_TEXTURE_2D, texID);
}




///////////////////////////////////////////////////////////////////////////
/// Set the name of the node											///
///////////////////////////////////////////////////////////////////////////
/// Input	: 
///		- the new name of the node
/// Output	: 
///		- set the new name of the node
/// Return	: NONE
void ZTexture::SetFileName(char * newName)
{
	filename = string(newName);
	renamed = true;
}

void ZTexture::SetFileName(string newName)
{
	filename = string((char*)newName.c_str());
	renamed = true;
}


























