/*----------------------------------------------------------------------
  File:    image.c
  Purpose: Stuff concerning textures
  Author:  Tomas Möller
           Department of Computer Engineering
           Chalmers University of Technology   
  History: July 1999 (started)
----------------------------------------------------------------------*/

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ppmimage.h"

/* skip all rows that start with #, i.e., comments */
static void eatComments(FILE *f)
{
   int ch;
   while((ch=getc(f))=='#')
   {
      char str[1000];
      fgets(str,1000,f);
   }
   ungetc(ch,f);   
}

static void eatWhitespace(FILE *f)
{
   int ch;
   ch=getc(f);
   while(ch==' ' || ch=='\t' || ch=='\n' || ch=='\f' || ch=='\r')
   {
      ch=getc(f);
   }
   ungetc(ch,f);
}

/* reads a ppm file with the P6 header (means raw RGB), returns a struct Texture */
/* the header looks like this:
 *---------
 * P6
 * # comments if you want to
 * width height
 * 255
 *---------
 * then follows RGBRGBRGBRGBRGB...
 */
bool fReadPPM(char *filename, int &width, int &height, unsigned char *&pixels)
{
   FILE *f;
   int colres;
   f=fopen(filename,"rb");
   if(f)
   {
      char str[100];
      eatWhitespace(f);
      eatComments(f);
      eatWhitespace(f);
      fscanf(f,"%s",str);
      if(strcmp(str,"P6")!=0)
      {
	 printf("Error: the texture image file must be of raw color PPM format,\n");
	 printf("i.e., it must have P6 in the header. File: %s\n",filename);
	 fclose(f);
	 return false;
      }
      eatWhitespace(f);
      eatComments(f);
      eatWhitespace(f);
      fscanf(f,"%d %d",&width,&height);
      if(width<=0 || height<=0)
      {
	 printf("Error: width and height of the image must be greater than zero. File: %s\n",filename);
	 fclose(f);
	 return false;
      }
      eatWhitespace(f);
      eatComments(f);
      eatWhitespace(f);
      fscanf(f,"%d",&colres);
      if(colres!=255)
      {
	 printf("Error: color resolution must be 255.File: %s\n",filename);
	 fclose(f);
	 return false;
      }

      /* gotta eat the newline too */
      char ch=0;
      while(ch!='\n') fscanf(f,"%c",&ch);


      pixels=new unsigned char[3*width*height];
      if(!pixels)
      {
	 printf("Error: could not allocate memory for the pixels of the texture. File: %s\n",filename);
	 fclose(f);
	 return false;	 
      }
      
      if(fread(pixels,3*width*height,1,f)!=1)
      {
	 printf("Error: could not read 3 x %d bytes of pixel info. File: %s\n",width*height,filename);
	 delete [] pixels;
	 fclose(f);
	 return false;
      }
            
      fclose(f);
      return true;
   }
   else
   {
      printf("Error: could not open %s.\n",filename);
      return false;
   }   
}

bool fWritePPMfromRGBA(char *filename, int width, int height, 
		       unsigned char *RGBApixels,bool reverse_y)
{
	FILE *f;
	f=fopen(filename,"wb");
	if(f)
	{
		int q;
		unsigned char *linebuffer=new unsigned char[3*width];
		fprintf(f,"P6\n%d %d\n255\n",width,height);
		for(q=0;q<height;q++)
		{
			unsigned char *adr;	 
			if(reverse_y) adr=RGBApixels+4*width*(height-1-q);
			else adr=RGBApixels+4*width*q;
			
			// now put the current line of RGBA into linebuffer (RGB)
			for(int x=0;x<width;x++)
			{
				linebuffer[3*x+0]=*adr++;
				linebuffer[3*x+1]=*adr++;
				linebuffer[3*x+2]=*adr++;
				adr++;
			} 
			
			fwrite(linebuffer,3*width,1,f);
		}
		delete [] linebuffer;
		fclose(f);
		return true;
	}
	else
	{
		printf("Error: could not open file <%s>.\n",filename);
		return false;
	}
}

bool fWrite3PPMfromRGBA(char *filename, int width1,int width2,int width3,int height,
			unsigned char *buffer1, unsigned char *buffer2,
			unsigned char *buffer3, bool reverse_y)
{
  FILE *f;
  f=fopen(filename,"wb");
  if(f)
  {
    unsigned char *adr1,*adr2,*adr3;	 
    unsigned char *tmpbuf;
    int y,q,x;
    unsigned char *linebuffer=new unsigned char[3*(width1+width2+width3)];
    fprintf(f,"P6\n%d %d\n255\n",width1+width2+width3,height);
    for(q=0;q<height;q++)
    {
      if(reverse_y) y=height-1-q;
      else y=q;

      adr1=buffer1+4*width1*y;
      adr2=buffer2+4*width2*y;
      adr3=buffer3+4*width3*y;

      tmpbuf=linebuffer;
      for(x=0;x<width1;x++)
      {
	*tmpbuf++=*adr1++;
	*tmpbuf++=*adr1++;
	*tmpbuf++=*adr1++;
	adr1++;
      }
      for(x=0;x<width2;x++)
      {
	*tmpbuf++=*adr2++;
	*tmpbuf++=*adr2++;
	*tmpbuf++=*adr2++;
	adr2++;
      }
      for(x=0;x<width3;x++)
      {
	*tmpbuf++=*adr3++;
	*tmpbuf++=*adr3++;
	*tmpbuf++=*adr3++;
	adr3++;
      } 
      
      fwrite(linebuffer,3*(width1+width2+width3),1,f);
    }
    delete [] linebuffer;
    fclose(f);
    return true;
  }
  else
  {
    printf("Error: could not open file <%s>.\n",filename);
    return false;
  }
}


bool fWritePPM(char *filename, int width, int height, unsigned char *pixels,bool reverse_y)
{
   FILE *f;
   f=fopen(filename,"wb");
   if(f)
   {
      int q;
      fprintf(f,"P6\n%d %d\n255\n",width,height);
      for(q=0;q<height;q++)
      {
	 unsigned char *adr;	 
	 if(reverse_y) adr=pixels+3*width*(height-1-q);
	 else adr=pixels+3*width*q;
	 fwrite(adr,3*width,1,f);
      }
      fclose(f);
      return true;
   }
   else
   {
      printf("Error: could not open file <%s>.\n",filename);
      return false;
   }
}

bool fWritePGM(char *filename, int width, int height, unsigned char *pixels,bool reverse_y)
{
   FILE *f;
   f=fopen(filename,"wb");
   if(f)
   {
      int q;
      fprintf(f,"P5\n%d %d\n255\n",width,height);
      for(q=0;q<height;q++)
      {
	 unsigned char *adr;	 
	 if(reverse_y) adr=pixels+width*(height-1-q);
	 else adr=pixels+width*q;
	 fwrite(adr,width,1,f);
      }
      fclose(f);
      return true;
   }
   else
   {
      printf("Error: could not open file <%s>.\n",filename);
      return false;
   }
}

bool fWritePPMfromLuminance(char *filename, int width, int height, 
					   unsigned char *pixels,bool reverse_y)
{
	FILE *f;
	f=fopen(filename,"wb");
	if(f)
	{
		int q;
		unsigned char *linebuffer=new unsigned char[3*width];
		fprintf(f,"P6\n%d %d\n255\n",width,height);
		for(q=0;q<height;q++)
		{
			unsigned char *adr;	 
			if(reverse_y) adr=pixels+width*(height-1-q);
			else adr=pixels+width*q;
			
			// now put the current line of RGBA into linebuffer (RGB)
			for(int x=0;x<width;x++)
			{
				unsigned char luminance = *adr++;
				linebuffer[3*x+0]=luminance;
				linebuffer[3*x+1]=luminance;
				linebuffer[3*x+2]=luminance;
			} 
			
			fwrite(linebuffer,3*width,1,f);
		}
		delete [] linebuffer;
		fclose(f);
		return true;
	}
	else
	{
		printf("Error: could not open file <%s>.\n",filename);
		return false;
	}
}

bool fConvertPPMToJPG(char *filename)
{
	// call the image converter 'convert.exe ppmUnicodeFileName ppmTmpFileName'	
	TCHAR args[2*MAX_PATH + 100];
	args[0] = NULL;
	TCHAR FileName0[2*MAX_PATH + 100];
	TCHAR FileName1[2*MAX_PATH + 100];
	int l=strlen(filename);
	for(int i=0; i<l; i++)
	{
		FileName0[i] = filename[i];
		FileName1[i] = filename[i];
		if(filename[i] == '.')
		{
			FileName0[i+1]=0;
			FileName1[i+1]=0;
			lstrcat(FileName0, TEXT("ppm"));
			lstrcat(FileName0, 0);
			lstrcat(FileName1, TEXT("jpg"));
			lstrcat(FileName1, 0);
			break;
		}
	}
	lstrcat(args, TEXT("convert.exe \""));
	lstrcat(args, FileName0);
	lstrcat(args, TEXT("\" \""));
	lstrcat(args, FileName1);
	lstrcat(args, TEXT("\""));
	
	//LPCSTR currentDirectory = szTempPath;		
	STARTUPINFO startupInfo = {sizeof(STARTUPINFO), NULL, NULL, NULL, NULL, NULL, NULL, NULL,
		NULL, NULL, NULL, NULL, NULL, NULL, NULL};
	PROCESS_INFORMATION ProcessInformation; 
	BOOL ok = CreateProcess(NULL, args, NULL, NULL, false,
		CREATE_DEFAULT_ERROR_MODE | CREATE_NO_WINDOW, NULL, NULL, &startupInfo , &ProcessInformation);

	return ok;
}

bool fConvertToPPM(char *filename)
{
	// call the image converter 'convert.exe ppmUnicodeFileName ppmTmpFileName'	
	TCHAR args[2*MAX_PATH + 100];
	args[0] = NULL;
	TCHAR FileName0[2*MAX_PATH + 100];
	TCHAR FileName1[2*MAX_PATH + 100];
	int l=strlen(filename);
	for(int i=0; i<l; i++)
	{
		FileName0[i] = filename[i];
		FileName1[i] = filename[i];
		if(filename[i] == '.')
		{
			FileName1[i+1]=0;
			lstrcat(FileName1, TEXT("ppm"));
			lstrcat(FileName1, 0);

			for(i++; i<l; i++)
				FileName0[i] = filename[i];
			FileName0[i]=0;
			break;
		}
	}
	lstrcat(args, TEXT("convert.exe \""));
	lstrcat(args, FileName0);
	lstrcat(args, TEXT("\" \""));
	lstrcat(args, FileName1);
	lstrcat(args, TEXT("\""));
	
	//LPCSTR currentDirectory = szTempPath;		
	STARTUPINFO startupInfo = {sizeof(STARTUPINFO), NULL, NULL, NULL, NULL, NULL, NULL, NULL,
		NULL, NULL, NULL, NULL, NULL, NULL, NULL};
	PROCESS_INFORMATION ProcessInformation; 
	BOOL ok = CreateProcess(NULL, args, NULL, NULL, false,
		CREATE_DEFAULT_ERROR_MODE | CREATE_NO_WINDOW, NULL, NULL, &startupInfo , &ProcessInformation);
	
	return ok;
}

