//Appendix 3.B - A Mask Convolution Program in C //+++++++++++++++++++++++++++++++++++++++++++++++++++++ // // >>>MDIP 3.1 - MASK DIGITAL IMAGE PROCESSING Program<<< // Linux Version -- Gnu C++ Compiler // (also UNIX Version with C++ Compiler) // // This program processes an input image with a user // supplied (user input) convolution mask, writes out result. // //------------------------------------------------------------------------------------------------------ // It makes calls to XV (Xview) to display original and // processed images on screen. Reprocessed images are updated // on the screen. //============================================================ // Version updated: Jul. 2002 //------------------------------------------------------------------------------------------------------ // This program processes a *.pgm image of raw data of size up // to 1280 (pixels wide) by M (pixels high) where M can be any // reasonable value, say 768, 1024, 1280, 4096, etc. The user // provides the input image file name and an image output file // where the results will be written. The output file is written // as a stream of characters where each is a gray scale value // of from 0 to 255. The output file is a *.pgm file (raw data). // ---------------------------------------------------------------------------------------------- // The mask height and width are selected so that each is one // of {3,5,7,9,11,13,15,17,19,21} independently of the other. // The user must input the mask. elements. // //============================================================ //------------------------P R O G R A M----------------------------------------------------------- //============================================================ // // main(); // heading(); display program heading // instruct(); displays instructions if selected // openfiles(); opens input & output image files // getmask(); gets convolution mask, multiplier from user // applymask(); does convolution with mask on input image // readhdr(); reads input image file header // getstrip(); reads strip of rows from input image file // convolve(); performs convolution of mask and row strip // writefile(); writes processed row to output image file // lastrows(); writes last rows (unprocessed) to output file // closefiles(); closes input and processed output image files // display(); displays original and processed image via XV //---------------------------------------------------------------------------------------------------------- # include # include # include //-------------------------------------------------------------------------------------------------------- void heading(void); void openfiles(void); void getmask(void); void applymask(void); void instruct(void); void display(void); //-------------------------------------------------------------------------------------------------------- int fin[21][1280]; int gout[21][1280]; float mask[21][21]; //values for convolution mask int MRows, NCols; //indices for rows and cols int p, q; //height/width of pxq mask int rowcount; //count of row being processed FILE *infptr, *outfptr; //input/output file pointers char infile[40]; char static outfile[40]; //names of input/output image files char key; //key to select instructions char display_File1[] = "Original_Image"; char display_File2[] = "Processed_Image"; int first_time; float factor; //multiplier of convolution mask //-------------------------------------------------------------------------------------------------------- //-----------------------------MAIN------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------- main() { void closefiles(); char changekey, stopkey; //key to process another image or stop //------------------(Put Heading on Screen)-------------------------------------------------------- do { heading(); if (key == 'i') instruct(); first_time = 1; do { //---------------(Open Input & Output Image Files)----------------------------------------- openfiles(); //----------------(Get Mask Entries & Multiplier)-------------------------------------------- getmask(); //---------------(Do Convolution on Image with Mask)------------------------------------- applymask(); //---------------(Display Image with XV Program)------------------------------------------ display(); //---------------(Select to Change this Image or Not)---------------------------------------- do { printf("\n Process this image again with new parameters (y/n): ?"); scanf("%1s",&changekey); } while ((changekey!='y') && (changekey!='Y') && (changekey!='n') && (changekey!='y')); } while ((changekey=='y') || (changekey=='Y')); //------------------(Close Any Open Image Files)--------------------------------------------- closefiles(); //----------------(Select Stop or Process Another Image)------------------------------------ do { printf("\n Enter to stop or to process another image "); scanf("%1s",&stopkey); } while ((stopkey != 's') && (stopkey != 'S') && (stopkey != 'i') && (stopkey != 'I')); //--------------------------------------------------------------------------------------------------- } while ((stopkey != 's') && (stopkey != 'S')); printf("\n Bye! Bye!\n"); return; } //end main() //---------------------------------------------------------------------------------------------------- //----------------------------HEADING---------------------------------------------------------- //---------------------------------------------------------------------------------------------------- void heading() { int i; for (i=0;i<16;i++) printf(" +\n"); printf(" MDIP Ver. 3.1 - Convolution Mask Digital Image Processing\n"); printf(" by Prof. Carl G. Looney\n"); printf(" Computer Science Department/171\n"); printf(" UNIVERSITY OF NEVADA\n"); printf(" Reno, NV 89557\n"); printf(" looney@cs.unr.edu\n"); printf(" Updated: Jul. 2002\n"); for (i=0;i<4;i++) printf(" +\n"); do { printf("\n Enter for instructions or to continue: "); scanf("%1s",&key); } while ((key != 'i') && (key != 'c') && (key != 'I') && (key != 'C')); return; }//end heading() //---------------------------------------------------------------------------------------------------- //---------------------------INSTRUCT---------------------------------------------------------- //---------------------------------------------------------------------------------------------------- void instruct(void) { printf("\n\n"); printf("\n\n"); printf("\n\n"); printf(" >> I N S T R U C T I O N S <<"); printf("\n\n"); printf(" This program processes RAW (packed) DATA *.PGM image files\n"); printf(" (from XView) for 0 - 255 GRAY LEVELS. The image processing is\n"); printf(" done via convolution with a pxq MASK that is entered by the\n"); printf(" user, where p,q are each in {3, 5, 7, 9, 11, 13}. The image\n"); printf(" file header must have 4 lines, and the third line must give\n"); printf(" N = number of columns and M = number of rows in the image.\n"); printf("------------------------------------------------------------\n\n"); printf(" P5 (Line 1: P5 => raw packed bytes, P2 => ASCII codes)\n"); printf(" # .... (Line 2: a comment)\n"); printf(" 640 480 (Line 3: no. columns and no. rows)\n"); printf(" 255 (Line 4: max. no. of gray levels - this may be on line 3 above)\n"); printf("-------------------------------------------------------------\n\n"); printf(" The input .PGM file is processed and the results are written\n"); printf(" to the .PGM output file. The mask MULTIPLIER is composed of\n"); printf(" integer inputs for NUMERATOR and DENOMINATOR.\n\n"); printf(" Please write the mask and multiplier parts on paper and enter.\n"); printf("--------------------------------------------------------------\n\n"); printf(" Use a text editor if you need to fix the 4 line header on the\n"); printf(" image file (e.g., XV may put in an extra comment line!).\n\n"); return; }//end instruct() //-------------------------------------------------------------------------------------------------------- //--------------------------OPENFILES-------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------- void openfiles(void) { void readhdr(void); if (first_time == 1) { printf("\n OPEN an image file\n"); printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); printf(" Enter name of *.pgm INPUT image file: ? "); scanf("%s",&infile); printf(" Enter name of *.pgm OUTPUT image file: ? "); scanf("%s",&outfile); } if ((infptr = fopen(infile, "r")) == NULL) { printf(" Can NOT open input image file: <%s>\n",infile); printf(" Exiting program..... "); exit(1); } else printf(" Input file <%s> opened sucessfully\n\n",infile); if ((outfptr = fopen(outfile,"w")) == NULL) { printf(" Can NOT open output image file <%s>\n\n",outfile); printf(" Exiting program....."); exit(1); } else printf(" Output file <%s> is opened sucessfully\n\n",outfile); readhdr(); return; }//end openfiles() //------------------------------------------------------------------------------------------------------ //----------------------------GETMASK----------------------------------------------------------- //------------------------------------------------------------------------------------------------------ void getmask() { char redo; //key to redo the input mask int i, j; float numer, denom; printf(".......+..........+............+...........+............+.......\n"); printf(" Image is to be processed by:\n"); printf(" -- convolutions MASK with mask MULTIPLIER\n"); printf(" -- it requires INTEGER entries\n\n"); do { do { printf("\n Enter height of convolution mask (3,5,7,9,11,13,15,17,19,21): ?"); scanf("%d",&p); } while ((p!=3) && (p!=5) && (p!=7) && (p!= 9) && (p!=11) && (p!=13) && (p!=15) && (p!=17) && (p!=19) && (p!=21)); do { printf(" Enter width of convolution mask (3,5,7,9,11,13,15,17,19,21): ?"); scanf("%d",&q); printf("\n"); } while ((q!=3) && (q!=5) && (q!=7) && (q!=9) && (q!=11) && (p!=13) && (q!=15) && (q!=17) && (q!=19) && (q!=21)); printf(" Enter mask multiplier NUMERATOR (integer): ?"); scanf("%f",&numer); printf("\n"); printf(" Enter mask multiplier DENOMINATOR (integer): ?"); scanf("%f",&denom); printf("\n\n"); factor = numer/denom; for (i=0;i to accept given mask or to redo it: ?"); scanf("%1s",&redo); printf("\n\n"); } while (redo == 'r'); }//end getmask() //---------------------------------------------------------------------------------------------------- //----------------------------APPLYMASK----------------------------------------------------- //---------------------------------------------------------------------------------------------------- void applymask() { void getstrip(void); void convolve(void); void writefile(void); void lastrows(void); void closefiles(void); int Mminusphalf, Nminusqhalf, Mend; int pm1, phalf, phalfp1; pm1 = p - 1; phalf = p/2; phalfp1 = phalf + 1; rowcount = 0; Mend = MRows - phalf; getchar(); //--------------------[Read Input Image Header]-------------------------------------------------- do { //------------[Read Strip of p Image Rows to Process]--------------------------------------- getstrip(); //-----------------[Convolve Row Strip with Mask]-------------------------------------------- convolve(); //--------------[Write Processed Row to Output File]----------------------------------------- writefile(); rowcount++; } while (rowcount < Mend); lastrows(); closefiles(); return; }//end applymask() //--------------------------------------------------------------------------------------------------------- //------------------------------READHDR------------------------------------------------------------ //--------------------------------------------------------------------------------------------------------- void readhdr() { int i, k, Maxgrays; char c, c1, buffer[128]; //-----------------------[Read PGM File Header]------------------------------------------------- printf("\n\n File <%s> Header Bytes:\n",infile); printf("------------------------------------------------------------\n"); k = 0; do { i = 0; do { c = fgetc(infptr); buffer[i] = c; i++; } while (c != '\n'); if (k == 0) { c1 = buffer[1]; if (c1 == '5') { printf("\n File is: \n",c1); } else { printf(" Image in WRONG format!! Quitting.........\n\n"); exit(0); } } buffer[i] = '\0'; k++; fprintf(outfptr,"%s",buffer); printf("%s",buffer); } while (k < 2); fscanf(infptr,"%d %d %d",&NCols, &MRows, &Maxgrays); c = fgetc(infptr); fprintf(outfptr,"%d %d", NCols, MRows); fprintf(outfptr,"%c %d %c",'\n', Maxgrays, '\n'); printf(" %d ",NCols); printf(" %d <-----(Width & Height)\n", MRows); printf(" %d <-----(Max. Gray Level)\n\n",Maxgrays); }//end readhdr() //--------------------------------------------------------------------------------------------------------- //-----------------------------GETSTRIP-------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------- void getstrip() { int row, col, rowp1, pm1, qm1; unsigned char item; //read in pixel as char pm1 = p - 1; qm1 = q-1; if (rowcount == 0) //in case of first base row, { for (row=0;row 255) pixnum = 255; pixelcol = colcount + qhalf; //get center col. of block gout[phalf][pixelcol] = pixnum; //write to output image file if ((rowcount < 1) && (colcount < 1)) { printf("\n First Processed Block:\n"); for (row=0;row to continue!\n"); getchar(); } colcount++; } while (colcount < Nend); //---------[complete the unprocessed ends of processed row]---------- for (col=0;col 0) { for (col=0;col