// preprocess file in s, write to d
int preprocess(const char* s, const char* d){
#define LSIZE 256
	char line[LSIZE], iline[LSIZE];
	FILE *sf   = fopen(s, "r");
	FILE *df   = fopen(d, "w");
	
	if(sf==NULL || df==NULL)
		return -1;
	
	while( fgets(line, LSIZE, sf)!= NULL ){
		if( sstartswith(line, LOOP, FALSE) ){
			char **lines=NULL, *arg;
			int nlines=0;
			int c,i;
			arg = getArg(line, 0);
			if(arg==NULL) return -1;
			c = atoi( arg );
			free(arg);
			while( fgets(line, LSIZE, sf)!= NULL && !sstartswith(line, "}", FALSE) ){
				lines = (char**)realloc(lines,(++nlines)*sizeof(char*));
				lines[nlines-1] = strdup(line);
			}
			while(c-- >0){
				int i;
				for(i=0; i<nlines; i++){
					fputs(lines[i],df);
					strcpy(iline,lines[i]);
				}
			}
			for(i=0; i<nlines; i++)
				free(lines[i]);
			free(lines);
		}else if( sstartswith(line, PAN, FALSE) ){
			Image start, ziel;
			stBuf sbuf;
			char *c;
			int n, i;
			double tau =1.0, *y, *p, *r, *v;
			
			SetImageDefaults(&start);
			SetImageDefaults(&ziel);
			
			
			c = getArg(line, 0);
			if(c==NULL) return -1;
			n = atoi(c);
			free(c);
			
			c = getArg(line, 1);
			if(c!=NULL){
				tau=atof(c);
				free(c);
			}
			// Last iline is start
			if( ReadImageDescription( &start, &sbuf, iline ))
				return -1;
			c =  fgets(line, LSIZE, sf);
			if(c==NULL || ReadImageDescription( &ziel, &sbuf, line ))
					return -1;
			y = schwenk( start.yaw, ziel.yaw, tau, n);
			p = schwenk( start.pitch, ziel.pitch, tau, n);
			r = schwenk( start.roll, ziel.roll, tau, n);
			v = schwenk( start.hfov, ziel.hfov, tau, n);
			for(i=0; i<n; i++){
				ziel.yaw = y[i];
				ziel.pitch = p[i];
				ziel.roll = r[i];
				ziel.hfov = v[i];
				imageLine(&ziel, &sbuf, line);
				fputs(line, df);
				strcpy(iline, line);
			}
			free(y); free(p); free(r); free(v);
		}else if( sstartswith(line, SPLINE, FALSE) ){
			char *c;
			Image im;
			stBuf sbuf;
			int n=0,i;
			double *X, *Y, *y, *p, *r, *v;
			
			
			// Determine number of args
			while((c=getArg(line,n)) != NULL){
				free(c);
				n++;
			}
			n++;
			X = (double*)malloc(n*sizeof(double));
			X[0] = 0;
			for(i=1; i<n; i++){
				c = getArg(line,i-1);
				X[i] = X[i-1] + atof(c);
				free(c);
			}
			y=(double*)malloc(n*sizeof(double));
			p=(double*)malloc(n*sizeof(double));
			r=(double*)malloc(n*sizeof(double));
			v=(double*)malloc(n*sizeof(double));
			
			// Read lines
			// start at previous line
			for(i=0; i<n; i++){
				if(i==0)
					strcpy(line,iline);
				else
					fgets(line, LSIZE, sf);
			
				SetImageDefaults(&im);
				if( ReadImageDescription( &im, &sbuf, line ))
					return -1;
				y[i]=im.yaw;
				p[i]=im.pitch;
				r[i]=im.roll;
				v[i]=im.hfov;
			}
			Y = spline(X, y, n, 0., 0.); free(y); y=Y;
			Y = spline(X, p, n, 0., 0.); free(p); p=Y;
			Y = spline(X, r, n, 0., 0.); free(r); r=Y;
			Y = spline(X, v, n, 0., 0.); free(v); v=Y;
			
			n = (int)(X[n-1]-X[0]+1.);

			for(i=0; i<n; i++){
				im.yaw = y[i];
				im.pitch = p[i];
				im.roll = r[i];
				im.hfov = v[i];
				imageLine(&im, &sbuf, line);
				fputs(line, df);
				strcpy(iline, line);
			}

			free(y); free(p); free(r); free(v);free(X);
		}else if( sstartswith(line, SKIP, FALSE) ){
			Image dummy;
			stBuf sbuf;
			char *c;
			int n;
			
			c = getArg(line, 0);
			if(c==NULL) return -1;
			n = atoi(c);
			free(c);
			
			SetImageDefaults( &dummy );
			strcpy(dummy.name,"skip");
			SetStitchDefaults( &sbuf );
			imageLine(&dummy, &sbuf, line);
			while(n-- >0){
				fputs(line, df);
			}
		}else if( sstartswith(line, GRID, FALSE) ){
		// GRID syntax: pitch_down, pitch_up, n_vert yaw_left, yaw_right, n_hor
			int n_vert, n_hor,i,k;
			double pitch_down, pitch_up, yaw_left, yaw_right, dp, dy;
			char* c;
			Image im;
			stBuf sbuf;
			
			if( (c = getArg(line, 0)) ==NULL) return -1;
			pitch_down = atof(c);
			free(c);
			if( (c = getArg(line, 1)) ==NULL) return -1;
			pitch_up = atof(c);
			free(c);
			if( (c = getArg(line, 2)) ==NULL) return -1;
			n_vert = atoi(c);
			free(c);
			if( (c = getArg(line, 3)) ==NULL) return -1;
			yaw_left = atof(c);
			free(c);
			if( (c = getArg(line, 4)) ==NULL) return -1;
			yaw_right = atof(c);
			free(c);
			if( (c = getArg(line, 5)) ==NULL) return -1;
			n_hor = atoi(c);
			free(c);
			
			// Read and parse image line
			fgets(line, LSIZE, sf);
			
			SetImageDefaults(&im);
			if( ReadImageDescription( &im, &sbuf, line ))
				return -1;
			
			dy =  (yaw_right - yaw_left)  / (n_hor-1);
			dp =  (pitch_up - pitch_down) / (n_vert-1);
			for(i=0; i<n_vert; i++){
				im.pitch = i * dp + pitch_down;
				for(k=0; k<n_hor; k++){
					im.yaw = k*dy + yaw_left;
					if(i==0 && k==0)
						strcpy(im.name,"");
					else
						strcpy(im.name,"same");						
					imageLine(&im, &sbuf, line);
					fputs(line, df);
					strcpy(iline, line);					
				}
			}			
		}else{
			fputs(line,df);
			strcpy(iline,line);
		}
	}
	fclose(sf);
	fclose(df);
	return 0;
}
int readJPEG(Image * im, fullPath * sfile)
{
    struct jpeg_decompress_struct cinfo;
    struct jpeg_error_mgr jerr;
    FILE *infile;
    char filename[256];
    int scan_lines_to_be_read, scan_lines_read;
    unsigned int i, scanheight;
    unsigned char *data;
    JSAMPARRAY sarray;
    JOCTET *ptr = NULL;
    unsigned int size  = 0; 



#ifdef __Mac__
    unsigned char the_pcUnixFilePath[256];      // added by Kekus Digital
    Str255 the_cString;
    Boolean the_bReturnValue;
    CFStringRef the_FilePath;
    CFURLRef the_Url;           //till here
#endif

    //PrintError("%s", sfile->name);        

    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_decompress(&cinfo);

    // Prepare the library for reading the ICC profile, see its source code
    // for further information
    jpegICCSetupReadICCProfile(&cinfo);

    if (GetFullPath(sfile, filename))
        return -1;

#ifdef __Mac__
    CopyCStringToPascal(filename, the_cString); //Added by Kekus Digital
    the_FilePath =
        CFStringCreateWithPascalString(kCFAllocatorDefault, the_cString,
                                       kCFStringEncodingUTF8);
    the_Url =
        CFURLCreateWithFileSystemPath(kCFAllocatorDefault, the_FilePath,
                                      kCFURLHFSPathStyle, false);
    the_bReturnValue =
        CFURLGetFileSystemRepresentation(the_Url, true, the_pcUnixFilePath,
                                         256);

    strcpy(filename, the_pcUnixFilePath);       //till here
#endif

    if ((infile = fopen(filename, "rb")) == NULL) {
        PrintError("can't open %s", filename);
        return -1;
    }

    jpeg_stdio_src(&cinfo, infile);

    jpeg_read_header(&cinfo, TRUE);

    jpeg_start_decompress(&cinfo);

    SetImageDefaults(im);
    im->width = cinfo.output_width;
    im->height = cinfo.output_height;
    if (cinfo.output_components != 3)
    {
        PrintError("Image must be rgb");
        fclose(infile);
        return -1;
    }


    im->bitsPerPixel = 24;
    im->bytesPerLine = im->width * 3;
    im->dataSize = im->width * 4 * im->height;
    im->data = (unsigned char **) mymalloc((size_t) im->dataSize);
    if (im->data == NULL)
    {
        PrintError("Not enough memory");
        fclose(infile);
        return -1;
    }

    scanheight = cinfo.rec_outbuf_height;
    sarray = (JSAMPARRAY) malloc(scanheight * sizeof(JSAMPROW));

    scan_lines_to_be_read = im->height;
    data = *(im->data);

    while (scan_lines_to_be_read)
    {
        for (i = 0; i < scanheight; i++)
        {
            sarray[i] = (JSAMPROW) (data + i * im->bytesPerLine);
        }

        scan_lines_read = jpeg_read_scanlines(&cinfo, sarray, scanheight);

        scan_lines_to_be_read -= scan_lines_read;
        data += scan_lines_read * im->bytesPerLine;
    }

    // read ICC profile 
    
    if (jpegICCReadProfile(&cinfo, &ptr, &size)) {
        
        im->metadata.iccProfile.size = size;        
        im->metadata.iccProfile.data = (char*) ptr;
    }

    jpeg_finish_decompress(&cinfo);
    jpeg_destroy_decompress(&cinfo);

    ThreeToFourBPP(im);
    free(sarray);


    fclose(infile);

    return 0;


}