/* sample PGM reader/writer for 24-354 General Robotics Lab 2 fall 2000: amperez * original version) spring 2002: bstolt * updated file reader * removed hard-coded filenames (segfaults!) * handle comments in headers * added some basic error checking * misc clean-up fall 2003: spieper * made it simpler to do all three operations in one shot. * improved names on output files. */ /* Dear reader, instead of reading in characters, read in ints. Your life will be a lot better. If you insist on reading in chars, then read in unsigned chars. Note that ints are bigger than chars */ typedef struct pgm { int w; int h; int max; int* pData; } pgm; #include #include #include /* This LoadPGM function is an updated version that will deal with comments in file headers and do at least some basic checking if the file can be opened or is the correct format. It does assume the file is actually a valid length once the header has been read. You are of course free to use your own file reading functions. */ void LoadPGM( char* filename, pgm* pPgm ) { FILE* ifp; int word; int nRead = 0; char readChars[256]; //open the file, check if successful ifp = fopen( filename, "r" ); if (!ifp) { printf("Error: Unable to open file %s.\n\n", filename); exit(1); } //read headers from file printf ("Reading PGM file: %s...\n", filename); fscanf (ifp, "%s", readChars); if (strcmp(readChars, "P2") == 0) { //valid file type //get a word from the file fscanf (ifp, "%s", readChars); while (readChars[0] == '#') { //if a comment, get the rest of the line and a new word fgets (readChars, 255, ifp); fscanf (ifp, "%s", readChars); } //ok, comments are gone //get width, height, color depth sscanf (readChars, "%d", &pPgm->w); fscanf (ifp, "%d", &pPgm->h); fscanf (ifp, "%d", &pPgm->max); // allocate some memory, note that on the HandyBoard you want to // use constant memory and NOT use calloc/malloc pPgm->pData = (int*)malloc(sizeof(int) * pPgm->w * pPgm->h); // now read in the image data itself for (nRead = 0; nRead < pPgm->w * pPgm->h; nRead++) { fscanf(ifp, "%d" ,&word); pPgm->pData[nRead] = word; // printf("nRead = %d %d\n",nRead,pPgm->pData[nRead]); } printf ("Loaded PGM. Size: %dx%d, Greyscale: %d \n", pPgm->w, pPgm->h, pPgm->max + 1); } else { printf ("Error: Read file type %s. Format unsupported.\n\n", readChars); exit(1); } fclose(ifp); } /* Simply saves the PGM file to a file whose name is in filename */ void WritePGM( char* filename, pgm* pPgm ) { FILE* ofp; int i,j; ofp = fopen(filename, "w"); if (!ofp) { printf("Error: Unable to open file %s.\n\n", filename); exit(1); } printf ("Writing ouput PGM: %s\n\n", filename); //write the header fprintf( ofp, "P2\n" ); fprintf( ofp, "%d %d\n", pPgm->w, pPgm->h ); fprintf( ofp, "%d\n", pPgm->max ); //write the image data for (i = 0; i < pPgm->h;i++) { for (j = 0; j < pPgm->w; j++) fprintf(ofp,"%d ",*(pPgm->pData + i * pPgm->w + j)); fprintf(ofp,"\n"); } fclose(ofp); } /* We gave you a freebie */ void Thresh( pgm* image, pgm *target, int n ) { int *imageBuff,*targetBuff; int size; size = image->w * image->h; imageBuff = image->pData; targetBuff = target->pData; while( size-- ) { if( *imageBuff < n ) { *targetBuff = 0; } else { *targetBuff = 255; } imageBuff++; targetBuff++; } } /* contrast */ void Contrast( pgm* image, pgm *target) { int *imageBuff,*targetBuff; int size; int low_val; int high_val; float scalar; int offset; size = image->w * image->h; imageBuff = image->pData; targetBuff = target->pData; //set initial values low_val = *imageBuff; high_val = *imageBuff; //search for high and low values while( size-- ) { if( *imageBuff < low_val ) { low_val = *imageBuff; } if( *imageBuff > high_val ) { high_val = *imageBuff; } imageBuff++; } imageBuff = image->pData; size = image->w * image->h; offset = low_val; scalar = 255/(float)(high_val - offset); while( size-- ) { *targetBuff = (int)((float)(*imageBuff - offset) * scalar); targetBuff++; imageBuff++; } imageBuff = image->pData; } void Hist( pgm* image, pgm *target) { int *imageBuff,*targetBuff; int size, i, j, high_val, low_val, offset, current; float scalar; long bins[256]; for(i = 0; i < 256; i++) bins[i] = 0; size = image->w * image->h; imageBuff = image->pData; targetBuff = target->pData; while( size-- ) { bins[*imageBuff] ++; imageBuff++; } high_val = bins[0]; low_val = bins[0]; //establish the highest and lowest bin values for(i = 0; i < 256; i++){ if(bins[i] > high_val) high_val = bins[i]; if(bins[i] < low_val) low_val = bins[i]; } //normalize offset = low_val; scalar = 255/(float)(high_val - offset); for(i = 0; i < 256; i++){ bins[i] = (long)((float)(bins[i] - offset) * scalar); } size = target->w * target->h; //generate histogram image for (i = 0; i < target->w; i++){ for(j = 0; j < target->h; j ++){ current = i + j*target->w; if(bins[i] <= target->h - j) *(targetBuff+current) = 255; else *(targetBuff+current) = 0; } } } int main(int argc, char * argv[]) { pgm *image, *threshed, *contrasted, *histogram; char filename[256]; int val; int errchk; //check if a filename was given, if not, ask for one if (argc > 1) { strcpy(filename, argv[1]); } else { printf ("Enter filename: "); scanf ("%s", filename); } if(strlen(filename)>220) { printf("filename too long\n"); exit(0); } //allocate memory for the pgm struct threshed = (pgm *) malloc (sizeof(pgm)); histogram = (pgm *) malloc (sizeof(pgm)); contrasted = (pgm *) malloc (sizeof(pgm)); image = (pgm *) malloc (sizeof(pgm)); //read the file LoadPGM(filename, image); contrasted->max=image->max; contrasted->w=image->w; contrasted->h=image->h; threshed->max=image->max; threshed->w=image->w; threshed->h=image->h; histogram->h=256; histogram->w=256; histogram->max=255; threshed->pData=malloc(sizeof(int)*threshed->w*threshed->h); contrasted->pData=malloc(sizeof(int)*contrasted->w*contrasted->h); histogram->pData=malloc(sizeof(int)*histogram->w*histogram->h); // --- now do something with the data --- //thresholding for instance... //get thresholding value if (argc > 2) { errchk = sscanf (argv[2], "%d", &val); } else { printf ("Enter threshold value: "); errchk = scanf ("%d", &val); } // make sure it's not really screwed up if (!errchk || val >= 255 || val < 0) { printf("Error: Bad thresholding value\n\n"); exit(1); } //run thresholding Thresh(image, threshed, val); //run contrasting Contrast(image,contrasted); //create your histogram Hist(image,histogram); //finally write the new files strcpy(filename+strcspn(filename, "."),"_threshed.pgm"); WritePGM(filename, threshed); strcpy(filename+strcspn(filename, ".")-strlen("_threshed"),"_contrasted.pgm"); WritePGM(filename, contrasted); strcpy(filename+strcspn(filename, ".")-strlen("_contrasted"),"_hist.pgm"); WritePGM(filename, histogram); //all done printf("Done. Have a nice day...\n\n"); return 0; }