#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#define _USE_MATH_DEFINES
#include <math.h>

/*
    Code Converts GIF files in RAW files
    Filters horizontally & Vertically 2->1
    Reads in Current directory
*/

typedef unsigned char u8;

typedef struct basic_image {
	int nc;
	int nl;
	u8 *p;
};

int newim(struct basic_image *im)
{
  if ((im->p = (u8 *) malloc(3*im->nc*im->nl))==NULL)
		return -1;

	return 0;
}

void freeim(struct basic_image *im)
{
  free(im->p);
}

int readim(char *s, struct basic_image *im)
{
	FILE *f;

  if ((f=fopen(s,"rb"))==NULL)
   return -1;

	fread(im->p,3*im->nc*im->nl,1,f);

	fclose(f);

	return 0;
}


int writergbim(char *s, struct basic_image *im)
{
	FILE *f;

  if ((f=fopen(s,"wb"))==NULL)
   return -1;

	fwrite(im->p,3*im->nc*im->nl,1,f);

	fclose(f);

	return 0;
}

int writeppmim(char *s, struct basic_image *im)
{
	FILE *f;

  if ((f=fopen(s,"wb"))==NULL)
   return -1;

	fprintf(f,"P6\n");
	fprintf(f,"%d %d 255\n",im->nc,im->nl);
	fwrite(im->p,3*im->nc*im->nl,1,f);

	fclose(f);

	return 0;

}

void	rdpixel(struct basic_image *im,int l,int c,u8 *r,u8 *v,u8 *b)
{
	u8 *p;

	p = im->p + 3*(im->nc*l+c);

	*r=*p++;
	*v=*p++;
	*b=*p;
}

void  wrpixel(struct basic_image *im,int l,int c,u8 r,u8 v,u8 b)
{
	u8 *p;

	p = im->p + 3*(im->nc*l+c);

	*p++=r;
	*p++=v;
	*p=b;

}

// gaussienne avec un rayon de 0.75
// 1/2PiS² * exp(-(x²+y²)/2S²)
// kernel de taille 3
// c = center, s = side, d = diagonale
// c = 76/255 = 1/(2*PI*S²) ==> S = sqrt(1/(2*PI*c)) = 0.73
// s = 30/255
// d = 12/255
//
void GCoeff(float S,double *c, double *s, double *d)
{
	double total;

	*c = 1/(2*M_PI*S*S);
	*s = 1/(2*M_PI*S*S)*exp(-1/(2*S*S));
	*d = 1/(2*M_PI*S*S)*exp(-2/(2*S*S));
	total = *c+4*(*s+*d);
	*c = *c/total;
	*s = *s/total;
	*d = *d/total;
}


int main(int argc, char **argv)
{

	char sodd[256];
	char sout[256];
	char head[256];
	char heado[256];
	char hhead[256];
	char syscmd[256];


	struct basic_image im_in, im_out;

	int i,l,c,nl,nc;
	u8 r,v,b;
	u8 r1,v1,b1,r2,v2,b2,r3,v3,b3;
	u8 r4,v4,b4,r5,v5,b5,r6,v6,b6;
	u8 r7,v7,b7,r8,v8,b8,r9,v9,b9;


	int n;
	int imstart, imend;

	double cc,sc,dc;

	if (argc<3)
	{
		printf("Syntax is :\n gif2x2y2tiff im#start im#end width height\n");
		exit(0);
	}


	imstart = atoi(argv[1]);;
	imend = atoi(argv[2]);;

	if (argc>3)
	{
		nc = atoi(argv[3]);
		nl = atoi(argv[4]);
	}
	else
	{
		nc = 1280*2;
		nl = 720*2;
	}


	im_in.nl = nl*2;
	im_in.nc = nc*2;

	im_out.nl = nl;
	im_out.nc = nc;

	newim(&im_in);
	newim(&im_out);



	GCoeff(0.75,&cc,&sc,&dc);

	for (n=imstart;n<=imend;n++)
	{
		sprintf(heado, "im%05d",n);
		sprintf(hhead,"im%05d",n);

		sprintf(sodd ,"%s.raw",heado);
		sprintf(sout, "_tmp.ppm",head);


		sprintf(syscmd,"gif2rgb -1 -o %s %s.gif",sodd,heado);
		system(syscmd);

		printf("\n%05d == %s ==>%s\n",n,sodd, sout);

		readim(sodd,&im_in);


		/* Filtrage et entrelacement */

		/* le tour */

		// copie la premiere et la derniere ligne inchangée

		for (c=0;c<nc;c++)
		{
			rdpixel(&im_in,0,2*c  ,&r,&v,&b);
			wrpixel(&im_out,0, c,  r, v,b);

			rdpixel(&im_in,2*nl-1,2*c  ,&r,&v,&b);
			wrpixel(&im_out,nl-1, c,  r, v,b);
		}

		// copie la premiere et la dernière colonne inchangée

		for (l=0;l<nl;l++)
		{
			rdpixel(&im_in,2*l,0  ,&r,&v,&b);
			wrpixel(&im_out,l, 0,  r, v,b);

			rdpixel(&im_in,2*l, 2*nc-1  ,&r,&v,&b);
			wrpixel(&im_out, l, nc-1,  r, v,b);
		}

		// filtre tout le reste
		for (l=1;l<nl-1;l++)
		{
			for (c=1;c<nc-1;c++)
			{
				rdpixel(&im_in, 2*l-1,2*c-1  ,&r1,&v1,&b1);
				rdpixel(&im_in, 2*l-1,2*c,     &r2,&v2,&b2);
				rdpixel(&im_in, 2*l-1,2*c+1  ,&r3,&v3,&b3);
				rdpixel(&im_in, 2*l,2*c-1     ,&r4,&v4,&b4);
				rdpixel(&im_in, 2*l,2*c,       &r5,&v5,&b5);
				rdpixel(&im_in, 2*l,2*c+1  ,  &r6,&v6,&b6);
				rdpixel(&im_in, 2*l+1,2*c-1  ,&r7,&v7,&b7);
				rdpixel(&im_in, 2*l+1,2*c,     &r8,&v8,&b8);
				rdpixel(&im_in, 2*l+1,2*c+1  ,&r9,&v9,&b9);

				r=(u8)  (  cc*r5 + sc*(r2+r4+r6+r8) + dc*(r1+r3+r7+r9) );
				v=(u8)  (  cc*v5 + sc*(v2+v4+v6+v8) + dc*(v1+v3+v7+v9) );
				b=(u8)  (  cc*b5 + sc*(b2+b4+b6+b8) + dc*(b1+b3+b7+b9) );

				wrpixel(&im_out,l,c,r,v,b);
			}
		}
		writeppmim(sout,&im_out);

		sprintf(syscmd,"raw2tiff -c packbits %s %s.tif",sout,hhead);
		puts(syscmd);
		system(syscmd);

		sprintf(syscmd,"del %s",sodd);
		system(syscmd);


	}

	sprintf(syscmd,"del %s",sout);
	system(syscmd);

	freeim(&im_in);
	freeim(&im_out);

	return 0;
}
