#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "math.h"

/*
	Program to experiment with lenticular sheet generation
	Expect a series of images of the form base0000.ppm, base0001.ppm, etc
	Supports forward or reverse image ordering
*/

typedef struct {
	unsigned char r,g,b;
} PIXEL;

void GetImageSize(char *,int *,int *);
void ReadImage(char *,int,int,PIXEL *);

int main(int argc,char **argv)
{
	int i,j,k,f,index;
	int inew,jnew;
	int dir = 1;
	int n,width,height,nwidth,nheight;
	char basename[64];
	char fname[128];
	PIXEL *lenticular,*image;
	PIXEL white = {255,255,255},black = {0,0,0};

	/* Check and get the command line arguments */
	if (argc < 3) {
		fprintf(stderr,"Usage: %s basename nimage [r]\n",argv[0]);
		exit(-1);
	}
	n = atoi(argv[2]);
	if (n < 2) {
		fprintf(stderr,"There must be at least 2 images\n");
		exit(-1);
	}
	if (argc > 3 && argv[3][0] == 'r')
		dir = -1;

	/* 
		Get the image size from the first image.
		All images must be the same size
	*/
	sprintf(fname,"%s%04d.ppm",argv[1],0);
	GetImageSize(fname,&width,&height);
	fprintf(stderr,"The images are all assumed to be %d by %d\n",width,height);

	/* Create an image for the combined image */
	nwidth  = n * width;
	nheight = n * height;
	if ((lenticular = malloc(nwidth*nheight*sizeof(PIXEL))) == NULL) {
		fprintf(stderr,"Malloc of lenticular image failed\n");
		exit(-1);
	}

	/* Make the whole image black */
	for (i=0;i<nwidth*nheight;i++) {
		lenticular[i].r = 0;
      lenticular[i].g = 0;
      lenticular[i].b = 0;
	}

	/* Create storage for the sub images */
	if ((image = malloc(width*height*sizeof(PIXEL))) == NULL) {
      fprintf(stderr,"Malloc of temporary image failed\n");
      exit(-1);
   }

	/* Read the images and create the combined image */
	for (f=0;f<n;f++) {
		if (dir == 1)
			sprintf(fname,"%s%04d.ppm",argv[1],f);
		else
			sprintf(fname,"%s%04d.ppm",argv[1],n-1-f);
		fprintf(stderr,"Adding image %s\n",fname);
		ReadImage(fname,width,height,image);
		for (i=0;i<width;i++) {
			for (j=0;j<height;j++) {
				for (k=0;k<n;k++) {
					inew = i * n + f;
					jnew = j * n + k;
					lenticular[jnew*nwidth+inew] = image[j*width+i];
				}
			}
		}
	}

	/* Write the final image as another ppm */
	fprintf(stderr,"The lenticular image is %d by %d\n",nwidth,nheight);
	printf("P3\n%d %d\n255\n",nwidth,nheight);
	for (j=0;j<nheight;j++) {
		for (i=0;i<nwidth;i++) {
			index = j * nwidth + i;
			putchar(lenticular[index].r);
			putchar(lenticular[index].g);
			putchar(lenticular[index].b);
		}
	}
}

void GetImageSize(char *fname,int *w,int *h)
{
	char junk[256];
	FILE *fptr;

	if ((fptr = fopen(fname,"r")) == NULL) {
		fprintf(stderr,"Failed to open %s\n",fname);
		exit(-1);
	}
	fgets(junk,255,fptr);
	if (strstr(junk,"P3") == NULL) {
		fprintf(stderr,"Failed to read expected PPM header from %s\n",fname);
		fprintf(stderr,"Expected \"P3\", got \"%s\"\n",junk);
		exit(-1);
	}
	if (fscanf(fptr,"%d %d",w,h) != 2) {
		fprintf(stderr,"Failed to read width and height from %s\n",fname);
		exit(-1);
	}
	
	fclose(fptr);
}

void ReadImage(char *fname,int w,int h,PIXEL *image)
{
	int i;
   char junk[256];
   FILE *fptr;

   if ((fptr = fopen(fname,"r")) == NULL) {
      fprintf(stderr,"Failed to open %s\n",fname);
      exit(-1);
   }
   fgets(junk,255,fptr);
   if (strstr(junk,"P3") == NULL) {
      fprintf(stderr,"Failed to read expected PPM header\n");
      fprintf(stderr,"Expected \"P3\", got \"%s\"\n",junk);
      exit(-1);
   }
	fgets(junk,255,fptr);
	fgets(junk,255,fptr);
   if (strstr(junk,"255") == NULL) {
      fprintf(stderr,"Failed to read expected PPM header\n");
      fprintf(stderr,"Expected \"255\", got \"%s\"\n",junk);
      exit(-1);
   }

	if (fread(image,sizeof(char),3*w*h,fptr) != 3*w*h) {
		fprintf(stderr,"Reading image file failed\n");
		exit(-1);
	}

   fclose(fptr);
}


