#include #include #include #include #include "mat_util.h" #include "ppm.h" // program gets passed ppm image filename and blur amount void usage(); void blurfunc( Var *image, int blursize, Image * filter); int loadFilter( char * filename, Image ** myFilter ); /* A global - determines whether or not a gaussian filter is being used. */ int FILTER; int main(int argc, char *argv[]) { char infilename[2048]; // hopefully path and filename not greater than 2K char outfilename[2048]; char filtfilename[2048]; char first; int val; int blursize; Var myImage; Image * myFilter = NULL; /* used for gaussian blur (or whatever blur). */ if (argc != 4) { usage(); exit(0); } /* Determine whether radius or filter filename is given. */ sprintf(infilename, "%s", argv[1]); sprintf(outfilename, "%s", argv[3]); first = argv[2][0]; val = first - '0'; printf("val: %d\n", val); if ((val <= 42 && val >= 17) || (val <= 74 && val >= 49) || (val == -2) || (val == -1)) { FILTER = TRUE; sprintf(filtfilename, "%s", argv[2]); fprintf(stderr,"%s: infilename = %s, filtfilename = %s; outfilename = %s; ... \n",argv[0],infilename,filtfilename,outfilename); blursize = loadFilter(filtfilename, &myFilter); } else if (val < 10 && val > 0) { FILTER = FALSE; blursize = atoi(argv[2]); fprintf(stderr,"%s: infilename = %s, blursize = %d; outfilename = %s; ... \n",argv[0],infilename,blursize,outfilename); } else { usage(); exit(0); } //if blursize is not odd. if ((blursize % 2) == 0) { usage(); exit(0); } // load ppm file into Image load_ppm_file(infilename, &myImage); switch( myImage.magic_number ) { case GREY_PGM :fprintf(stderr,"%s is a pgm\n", infilename); break; case RGB_PPM :fprintf(stderr,"%s is a ppm\n", infilename); break; case GREY_PDM :fprintf(stderr,"%s is a grayscale pdm\n", infilename); break; case RGB_PDM :fprintf(stderr,"%s is a color pdm\n", infilename); break; case GREY_PLM :fprintf(stderr,"%s is a greyscale plm\n", infilename); break; case RGB_PLM :fprintf(stderr,"%s is a color plm\n", infilename); break; default :fprintf(stderr,"blur couldn't determine type of input\n"); return -1; } // blur it blurfunc(&myImage, blursize, myFilter); // write image back to disk save_pgm_file(&myImage, outfilename); return(1); } void blurfunc( Var *image, int blursize, Image *filter ) { Var *ANS, *ANS2; int m,n,k,i,j,index; Image tmp; int channels = image->channels; int width, halfblur; ANS = (Var *)calloc(1, sizeof(Var)); ANS2 = (Var *)calloc(1, sizeof(Var)); init_var(ANS, image->name, image->M, image->N, IMAGE, channels); init_var(ANS2, image->name, image->M, image->N, IMAGE, channels); /* This is a gaussian blur. */ if (FILTER == TRUE) { if (channels == GREY_SCALE) { // blur in the across direction (easy even with small amount of cache): for( m=0 ; mM ; m++ ) { for( n=0 ; nN ; n++ ) { tmp = 0; index = m*image->N +n; if( nimage[index +k]*filter[i]; ANS->image[index] = tmp; } else if( n>=image->N-blursize/2 ) // right edge { for( k=-blursize/2, i=0 ; kN-n ; k++, i++ ) tmp+=image->image[index +k]*filter[i]; ANS->image[index] = tmp; } else { for( k=-blursize/2, i=0 ; k<=blursize/2 ; k++, i++ ) tmp += image->image[index + k]*filter[i]; ANS->image[index] = tmp; } } } //blur in the down direction (same order, in case small number lines in cache): for( m=0 ; mM ; m++ ) { for( n=0 ; nN ; n++ ) { tmp = 0; // CLA (clear the accumulator) if( mimage[(m+k)*image->N +n]*filter[i]; ANS2->image[m*image->N + n] = tmp; } else if( m>=image->M-blursize/2 ) // bottom edge { for( k=-blursize/2, i=0 ; kM-m ; k++, i++ ) tmp+=ANS->image[(k+m)*image->N +n]*filter[i]; ANS2->image[m*image->N + n] = tmp; } else // not at edges { tmp = 0; for( k=-blursize/2, i=0 ; k<=blursize/2 ; k++, i++ ) tmp += ANS->image[(m+k)*image->N + n]*filter[i]; ANS2->image[m*image->N + n] = tmp; } } } } else if (channels == RGB24) { width = image->N*channels; halfblur = blursize/2*channels; // blur in the across direction (easy even with small amount of cache): for( m=0 ; mM ; m++ ) { index = m*width; for( n=0 ; nimage[index +k]*filter[i]; /* Accumulate the pixels to the left of the starting point */ for( k=n-channels, i=(blursize/2)-1; k>=0; k-=channels, i-- ) tmp+=image->image[index + k]*filter[i]; ANS->image[index + n] = tmp; } else if( n>=width-halfblur ) // right edge { for( k=-halfblur, i=0; kimage[index +n +k]*filter[i]; ANS->image[index + n] = tmp; } else { for( k=-halfblur, i=0 ; k<=halfblur ; k+=channels, i++ ) tmp+=image->image[index +n +k]*filter[i]; ANS->image[index + n] = tmp; } } } //blur in the down direction (same order, in case small number lines in cache): for( m=0 ; mM ; m++ ) { for( n=0 ; nimage[(m+k)*width +n]*filter[i]; ANS2->image[m*width + n] = tmp; } else if( m>=image->M-blursize/2 ) // bottom edge { for( k=-blursize/2, i=0 ; kM-m ; k++, i++ ) tmp+=ANS->image[(k+m)*width +n]*filter[i]; ANS2->image[m*width + n] = tmp; } else // not at edges { tmp = 0; for( k=-blursize/2, i=0 ; k<=blursize/2 ; k++, i++ ) tmp += ANS->image[(m+k)*width + n]*filter[i]; ANS2->image[m*width + n] = tmp; } } } } } else { /* This is not a gaussian blur */ if (channels == GREY_SCALE) { // blur in the across direction (easy even with small amount of cache): for( m=0 ; mM ; m++ ) { for( n=0 ; nN ; n++ ) { tmp = 0; if( nimage[m*image->N +n +k]; } ANS->image[m*image->N + n] = (tmp/(n+1+blursize/2)); } else if( n>=image->N-blursize/2 ) // right edge { for( k=-blursize/2 ; kN-n ; k++ ) tmp+=image->image[m*image->N +n +k]; ANS->image[m*image->N + n] = (tmp/(image->N-n+blursize/2)); } else { for( k=-blursize/2 ; k<=blursize/2 ; k++ ) tmp += image->image[m*image->N + n + k]; ANS->image[m*image->N + n] = (tmp/blursize); } } } //blur in the down direction (same order, in case small number lines in cache): for( m=0 ; mM ; m++ ) { for( n=0 ; nN ; n++ ) { tmp = 0; // CLA (clear the accumulator) if( mimage[(m+k)*image->N +n]; ANS2->image[m*image->N + n] = (tmp/(m+1+blursize/2)); } else if( m>=image->M-blursize/2 ) // bottom edge { for( k=-blursize/2 ; kM-m ; k++ ) tmp+=ANS->image[(k+m)*image->N +n]; ANS2->image[m*image->N + n] = (tmp/(image->M-m+blursize/2)); } else // not at edges { tmp = 0; for( k=-blursize/2 ; k<=blursize/2 ; k++ ) tmp += ANS->image[(m+k)*image->N + n]; ANS2->image[m*image->N + n] = (tmp/blursize); } } } } else if (channels == RGB24) { width = image->N*channels; halfblur = blursize/2*channels; // blur in the across direction (easy even with small amount of cache): for( m=0 ; mM ; m++ ) { for( n=0 ; nimage[m*width +k]; /* Accumulate the pixels to the left of the starting point */ for( k=n-channels; k>=0; k-=channels, i++ ) tmp+=image->image[m*width + k]; ANS->image[m*width + n] = (tmp/i); } else if( n>=width-halfblur ) // right edge { for( k=-halfblur, i=0; kimage[m*width +n +k]; ANS->image[m*width + n] = (tmp/i); } else { for( k=-halfblur ; k<=halfblur ; k+=channels ) tmp+=image->image[m*width +n +k]; ANS->image[m*width + n] = (tmp/blursize); } } } //blur in the down direction (same order, in case small number lines in cache): for( m=0 ; mM ; m++ ) { for( n=0 ; nimage[(m+k)*width +n]; ANS2->image[m*width + n] = (tmp/(m+1+blursize/2)); } else if( m>=image->M-blursize/2 ) // bottom edge { for( k=-blursize/2 ; kM-m ; k++ ) tmp+=ANS->image[(k+m)*width +n]; ANS2->image[m*width + n] = (tmp/(image->M-m+blursize/2)); } else // not at edges { tmp = 0; for( k=-blursize/2 ; k<=blursize/2 ; k++ ) tmp += ANS->image[(m+k)*width + n]; ANS2->image[m*width + n] = (tmp/blursize); } } } } } /* - - Copy answer to original image - - */ copy_image(ANS2, image); /* - - Free OLD image - - */ free(ANS2->image); free(ANS->image); } void usage() { fprintf(stderr, "Usage: ./blur v001.ppm filter.ppm out.ppm\n"); fprintf(stderr, " : ./blur v001.ppm 7 out.ppm\n"); fprintf(stderr, "only supports odd valued blur radii\n"); } /* Given a filename and a 1-D array, loads the contents of the file into * the array. Array can be no longer than 500 elements. * Returns the number of elements read in (length of array). */ int loadFilter( char * filename, Image ** myFilter ) { /* Assume the filter is no longer than 500 elements. */ float buffer[500]; FILE * file_ptr; int result = 0; int i = -1; int j; file_ptr = fopen(filename, "r"); while (result != EOF){ i++; result = fscanf(file_ptr, "%f", &(buffer[i])); } *myFilter = (Image *) malloc(i*sizeof(Image)); if (myFilter == NULL) { fprintf(stderr, "Unable to malloc in loadFilter.\n"); exit(0); } /* Copy filter from buffer. */ for (j=0; j