#include #include #include #include #include #include #include #include #include #include #include #include "cement.h" #include "pnmutils.h" #include "file.h" /* Global Variables */ extern int errno; extern char **environ; /* Function prototypes needed in executable and in library */ static int my_system (char *command); static inline double createValue(double a, unsigned char b, double weight); static int verbose=0; static double powLookupTable[256]; static double exponent; static int convert = 0; static int grayscale = 0; static int newfile = 0; #ifndef OBJECT_COMPILE /* Functions needed only in executable */ void usage(char * string); void parse_commandline(int argc, char ** argv, char**input_filenameA, char**input_filenameB, double *R, double *G, double *B, double *yR, double *yG, double *yB); void mystatus(char *action, char *filename, double R,double G, double B, double complete); #endif void readlut(char *lutfilename); /* Functions */ #ifndef CEMENT_REMOVE int cementi(char *input_filenameA, char *input_filenameB, double R, double G, double B, double yR, double yG, double yB, char* command, void (*status)(char *action, char *filename, double R,double G, double B, double complete) ) #else int cemento(char *input_filenameA, char *input_filenameB, double R, double G, double B, double yR, double yG, double yB, char* command, void (*status)(char *action, char *filename, double R,double G, double B, double complete) ) #endif { struct image_params a_params={NULL,0,0,0,0,0.0}; struct image_params b_params={NULL,0,0,0,0,0.0}; File * a, * b, * dest, * new; double p; /* exponent for pow */ double a_pixel[ARRAY_SIZE]; unsigned char b_pixel[ARRAY_SIZE]; double out_pixel[ARRAY_SIZE]; int i, j, k, exp; int channels_per_pixel; char * lut_filename; // double R, G, B; /* weights for cement */ double new_pixel; double * newimage; /* Timing measurments */ struct timeval timeValStart; struct timeval timeValEnd; struct timezone timeZone; int minutes; double seconds=0.0; #ifdef GET_TIME_MEASUREMENTS struct timeval runTimeStart; struct timeval runTimeStop; double fileReadTime=0.0; double fileWriteTime=0.0; double computeTime=0.0; #endif unsigned int pixels=0; unsigned int numberOfPixels; char string[MAX_STRING_LENGTH]; unsigned int image_ptr=0; a_params.filename=input_filenameA; b_params.filename=input_filenameB; // parse_commandline(argc, argv, &a_params, &b_params, &R, &G, &B); if ((a=fileopen(a_params.filename, "r"))==NULL) { fprintf(stderr, "Unable to open %s.\n", a_params.filename); fprintf(stderr, "Creating a new file.\n"); newfile = 1; } if ((b=fileopen(b_params.filename, "r"))==NULL) { fprintf(stderr, "Unable to open %s.\n", b_params.filename); exit(EXIT_FAILURE); } sprintf(string,"tmp.%s",a_params.filename); if ((dest=fileopen(string, "w"))==NULL) { fprintf(stderr, "Unable to open %s.\n", string); exit(EXIT_FAILURE); } if(newfile == 1) { a_params.type='A'; channels_per_pixel=3; sprintf(string, "P%c\n", a_params.type); filewrite(string,sizeof(unsigned char),strlen(string),dest); } else { get_image_type(a, &a_params); if(a_params.type=='A') { channels_per_pixel=3; sprintf(string, "P%c\n", a_params.type); filewrite(string,sizeof(unsigned char),strlen(string),dest); get_image_params_preserve_comments(a,&a_params,dest); } else { fprintf(stderr, "Portable Lightspace Map (plm) must be type A and it is type %c\n",a_params.type); exit(EXIT_FAILURE); } } if(isJpegFile(b)==0) { get_image_params(b, &b_params); if(b_params.type=='5') grayscale = 1; } else { b_params.type='6'; b_params.max_val=255; p = exponent = a_params.exponent; lut_filename = (char*) malloc(50 * sizeof(char)); exp = rint(p * 10.0); sprintf(lut_filename, "powLookup%d.txt", exp); printf("p: %6g exp: %d filename: %s\n", p, exp, lut_filename); if(lut_filename !=NULL) { readlut(lut_filename); } if(read_JPEG_file (b_params.filename)==0) { printf("ERROR: File %s does not exist\n",b_params.filename); exit(0); } // write_JPEG_file("test.jpg",95); // exit(0); image_ptr=0; b_params.width=image_width; b_params.height=image_height; } if(newfile == 1) { /* Create a new plm file and initialize it with zeros. */ /* This is a kludge, but a lot easier than trying to rewrite the code to get rid of all the file reads. */ new = fileopen(a_params.filename, "w"); if (new->fp == NULL) { fprintf(stderr,"Couldn't open new file either!\n"); exit(EXIT_FAILURE); } fprintf(new->fp, "PA\n"); fprintf(new->fp, "%d %d\n", b_params.width, b_params.height); fprintf(new->fp, "255\n"); fprintf(new->fp, "2\n"); /* don't know what this field is */ fprintf(new->fp, "%2g\n", EXPONENT); newimage = calloc(b_params.width*b_params.height, sizeof(double)); if (newimage == NULL) { fprintf(stderr, "Unable to allocate.\n"); exit(EXIT_FAILURE); } fwrite(newimage, sizeof(double), b_params.width*b_params.height, new->fp); fclose(new->fp); /* Now open it again and pretend it's the original plm file we were given. */ a = fileopen(a_params.filename, "r"); if (a->fp==NULL) { fprintf(stderr, "Unable to open %s after supposed creation.\n", a_params.filename); exit(EXIT_FAILURE); } get_image_type(a,&a_params); /* to move the pointer along */ get_image_params_preserve_comments(a,&a_params,dest); } p = exponent = a_params.exponent; lut_filename = (char*) malloc(50 * sizeof(char)); exp = rint(p * 10.0); sprintf(lut_filename, "powLookup%d.txt", exp); if(lut_filename !=NULL) { readlut(lut_filename); } if ((a_params.width!=b_params.width) || (a_params.height!=b_params.height) || (a_params.max_val!=b_params.max_val)) { printf("%f %f\n",a_params.exponent,EXPONENT); printf("%d %d\n",a_params.width,b_params.width); printf("%d %d\n",a_params.height,b_params.height); printf("%d %d\n",a_params.max_val,b_params.max_val); fprintf(stderr, "Lightspace must have the same dimensions, maximum " "values, and exponent.\n"); exit(EXIT_FAILURE); } sprintf(string, "# %s %s %s %f %f %f\n",command,input_filenameA,input_filenameB,R, G,B); filewrite(string,sizeof(unsigned char),strlen(string),dest); #ifndef CEMENT_REMOVE sprintf(string, "%d %d\n%d\n%d\n%f\n",a_params.width, a_params.height,a_params.max_val, ++a_params.numberOfImages,exponent); #else sprintf(string, "%d %d\n%d\n%d\n%f\n",a_params.width, a_params.height, a_params.max_val,--a_params.numberOfImages,exponent); #endif filewrite(string,sizeof(unsigned char),strlen(string),dest); #ifdef SILENT_RUN #ifndef CEMENT_REMOVE // printf("Add %s %d %d %d\r",b_params.filename,(int)R,(int)G,(int)B); #else // printf("Del %s %d %d %d\r",b_params.filename,(int)R,(int)G,(int)B); #endif #else #ifndef CEMENT_REMOVE printf("Adding file: \"%s\", ",b_params.filename); #else printf("Removing file: \"%s\", ",b_params.filename); #endif printf("P%c, %dx%d, ",b_params.type,b_params.width,b_params.height); printf("R=%7.3f ",R); printf("G=%7.3f ",G); printf("B=%7.3f to ",B); printf("lightspace \"%s\", ",a_params.filename); printf("P%c\n",a_params.type); #endif /* Start Timer */ if(gettimeofday(&timeValStart,&timeZone)==-1) { fprintf(stderr,"Error getting the time\n"); exit(0); } numberOfPixels=a_params.width*a_params.height; if(((float)numberOfPixels/NUMBER_PIXELS_PER_READ)!=(int)((float)numberOfPixels/NUMBER_PIXELS_PER_READ)) { if(verbose) printf("\nERROR: The number of pixels %d is not evenly divisible by %d. ",numberOfPixels,NUMBER_PIXELS_PER_READ); numberOfPixels=(int)((float)numberOfPixels/NUMBER_PIXELS_PER_READ)*NUMBER_PIXELS_PER_READ; if(verbose) printf("We will go up to %d pixels.\n",numberOfPixels); } for(i=0;i60) { minutes=seconds/60; seconds=seconds-minutes*60; } else minutes=0; if(verbose || GET_RUN_TIME) { #ifndef SILENT_RUN if(minutes==1) printf("Run Time is about %d minute %f seconds.\n",minutes,seconds); else printf("Run Time is about %d minutes %f seconds.\n",minutes,seconds); #else #ifndef CEMENT_REMOVE // printf("Add %s %d %d %d %4.2f(s)\n",b_params.filename,(int)R,(int)G,(int)B,minutes*60+seconds); if(status!=NULL) status("Add",b_params.filename,R,G,B,(double)100); #else // printf("Del %s %d %d %d %4.2f(s)\n",b_params.filename,(int)R,(int)G,(int)B,minutes*60+seconds); if(status!=NULL) status("Del",b_params.filename,R,G,B,(double)100); #endif #endif } if(isJpegFile(b)==1) free(image_buffer); sprintf(string,"rm %s; mv tmp.%s %s",a_params.filename,a_params.filename,a_params.filename); if(verbose) printf("%s\n",string); if(my_system (string)==-1) { printf("Error calling %s\n",string); exit(EXIT_FAILURE); } return(EXIT_SUCCESS); } /**************************************************************************/ static inline double createValue(double a, unsigned char b, double weight) { #ifndef CEMENT_REMOVE return(a+weight*powLookupTable[b]); #else return(a-weight*powLookupTable[b]); #endif } /**************************************************************************/ static int my_system (char *command) { int pid, status; if (command == 0) return 1; pid = fork(); if (pid == -1) return -1; if (pid == 0) { char *argv[4]; argv[0] = "sh"; argv[1] = "-c"; argv[2] = command; argv[3] = 0; execve("/bin/sh", argv, environ); exit(127); } do { if (waitpid(pid, &status, 0) == -1) { if (errno != EINTR) return -1; } else return status; } while(1); } #ifndef OBJECT_COMPILE int main(int argc, char ** argv) { char * input_filenameA=NULL; char * input_filenameB=NULL; double R,G,B,yR,yG,yB; parse_commandline(argc, argv, &input_filenameA,&input_filenameB,&R,&G,&B,&yR,&yG,&yB); #ifndef CEMENT_REMOVE return(cementi(input_filenameA, input_filenameB,R,G,B,yR,yG,yB,argv[0],mystatus)); #else return(cemento(input_filenameA, input_filenameB,R,G,B,yR,yG,yB,argv[0],mystatus)); #endif } void mystatus(char *action, char *filename, double R,double G, double B, double complete) { printf("%s %s %d %d %d %d%%\r",action,filename,(int)R,(int)G,(int)B,(int)complete); fflush(stdout); if((int)complete==100) printf("\n"); } void usage(char * string) { fprintf(stderr, "Use: %s [Lightspace file] [Imagespace file] \n",string); fprintf(stderr, " [Lightspace file] is Portable Lightspace Map (plm) file image to be added to\n"); fprintf(stderr, " [Imagespace file] is ppm file of image to add to the lightspace.\n"); fprintf(stderr, " =Float for Red weight.\n"); fprintf(stderr, " =Float for Green weight.\n"); fprintf(stderr, " =Float for Blue weight.\n"); fprintf(stderr, " <-y>=Convert ppm input to pgm before cementing.\n"); exit(EXIT_SUCCESS); } void parse_commandline(int argc, char ** argv, char**input_filenameA, char**input_filenameB, double *R, double *G, double *B, double *yR, double *yG, double *yB) { if (argc<6) usage(argv[0]); *input_filenameA=(char*)strdup(argv[1]); *input_filenameB=(char*)strdup(argv[2]); sscanf(argv[3],"%lf",R); /* sscanf does not recognize %g, must be %lf */ sscanf(argv[4],"%lf",G); /* sscanf does not recognize %g, must be %lf */ sscanf(argv[5],"%lf",B); /* sscanf does not recognize %g, must be %lf */ if(argc==10) { if (strcmp("-y", argv[6]) == 0) { convert = 1; printf("averaging color image to get grayscale\n"); sscanf(argv[7],"%lf",yR); /* sscanf does not recognize %g, must be %lf */ sscanf(argv[8],"%lf",yG); /* sscanf does not recognize %g, must be %lf */ sscanf(argv[9],"%lf",yB); /* sscanf does not recognize %g, must be %lf */ } else usage(argv[0]); } } /* ===================================================================== */ /* ===================================================================== */ /* ===================================================================== */ /* Readlut - reads a given lookup table. */ void readlut(char *lutfilename) { // some variables used in reading a text file lut FILE *lutfile; int lutsize=256; float p; int i; if(lutfilename !=NULL) { if ((lutfile = fopen(lutfilename, "r")) == NULL) { fprintf(stderr, "Unable to open %s.\n", lutfilename); fclose(lutfile); exit(EXIT_FAILURE); } else { fscanf(lutfile, "%f", &p); for (i=0; i