/* Author: Jonathan Hardy file: robinson.cc This file reads in a PGM image file and processes it with the Robinson edge detector algorithm. The processed image is then written out to a new PGM image file with "_rbsn" appended to the original filename. The arguments are as follows: robinson */ #include #include #include #include FILE *ptr; // Image File FILE *rbsnptr; // Output File void main(int argc, char**argv) { char fname[13]; // Image filename char rbsnname[18]; // Output filename char width[4], height[4], numcol[4]; // Image information char Type[3]; // Image type (P5) int r, c, data; // Counters and image data variable char temp[100]; // Variable for input comment lines char comment[17]; // Variable for output comment /* The following section reads the image file */ strcpy(fname, argv[1]); // Get filename from command line strcat(fname, ".pgm"); // Append filename with ".pgm" const int ulimit = atoi(argv[2]); // Get upper threshold const int llimit = atoi(argv[3]); // Get lower threshold const int thresh = atoi(argv[4]); // Get output threshold ptr = fopen(fname, "rb"); // Open image file fread(&Type, 3, 1, ptr); // Get image type fread(&width, 4, 1, ptr); // If no comment lines, get width while (width[0] == '#'){ // Otherwise, ignore comment lines fgets(temp, 100, ptr); // and get width fread(&width, 4, 1, ptr); } fread(&height, 4, 1, ptr); // Get height const int WIDTH = atoi(width); const int HEIGHT = atoi(height); int ImgArray[HEIGHT][WIDTH]; // Create image array fread(&numcol, 4, 1, ptr); // Get number of colors (255) for (r = 0; r < HEIGHT; r++){ // Get image data and threshold it for (c = 0; c < WIDTH; c++){ data = fgetc(ptr); if ((data < llimit) || (data > ulimit)) ImgArray[r][c] = 0; else ImgArray[r][c] = data; } } fclose(ptr); // Close image file /* The following section processes the image data */ strcpy(rbsnname, argv[1]); strcat(rbsnname, "_rbsn.pgm"); int RbsnArray[HEIGHT][WIDTH]; // Create array for processed data int dw, dx, dy, dz, di; // Mask response variables float maxResp = 1; // Variable for maximum response float factor = 1; // Variable for scaling factor /* The following iteration scans the image array and performs the mask convolutions for the Robinson algorithm. It calculates the magnitude response by finding the maximum of all the responses. */ for (r = 1; r < HEIGHT - 1; r++){ RbsnArray[r][0] = 0; RbsnArray[r][WIDTH-1] = 0; for (c = 1; c < WIDTH - 1; c++){ dw = ImgArray[r][c-1] + 2*ImgArray[r-1][c-1] + ImgArray[r-1][c] - ImgArray[r][c+1] - 2*ImgArray[r+1][c+1] - ImgArray[r+1][c]; dx = ImgArray[r-1][c-1] + 2*ImgArray[r-1][c] + ImgArray[r-1][c+1] - ImgArray[r+1][c-1] - 2*ImgArray[r+1][c] - ImgArray[r+1][c+1]; dy = ImgArray[r-1][c-1] + 2*ImgArray[r][c-1] + ImgArray[r+1][c-1] - ImgArray[r-1][c+1] - 2*ImgArray[r][c+1] - ImgArray[r+1][c+1]; dz = ImgArray[r-1][c] + 2*ImgArray[r-1][c+1] + ImgArray[r][c+1] - ImgArray[r+1][c] - 2*ImgArray[r+1][c-1] - ImgArray[r][c-1]; di = abs(dw); if ((abs (dx)) > di) di = abs(dx); if ((abs (dy)) > di) di = abs(dy); if ((abs (dz)) > di) di = abs(dz); RbsnArray[r][c] = di; if (di > maxResp) maxResp = di; } } /* This section takes care of the edges */ for (c = 0; c < WIDTH; c++){ RbsnArray[0][c] = 0; RbsnArray[HEIGHT-1][c] = 0; } /* This section scales the output array for writing to a 255-level grayscale image */ factor = maxResp/255; for (r = 0; r < HEIGHT; r++){ for (c = 0; c < WIDTH; c++){ RbsnArray[r][c] = (int)(RbsnArray[r][c] / factor); } } /* This section thresholds out small responses */ for (r = 0; r < HEIGHT; r++){ for (c = 0; c < WIDTH; c++){ if (RbsnArray[r][c] < thresh){RbsnArray[r][c] = 0;} } } /* This section writes the output to a new PGM file */ rbsnptr = fopen(rbsnname, "wb"); fwrite(&Type, 3, 1, rbsnptr); comment = "# New pgm file.\n"; fwrite(&comment, 16, 1, rbsnptr); fwrite(&width, 4, 1, rbsnptr); fwrite(&height, 4, 1, rbsnptr); fwrite(&numcol, 4, 1, rbsnptr); for (r = 0; r < HEIGHT; r++){ for (c = 0; c < WIDTH; c++){ fputc(RbsnArray[r][c], rbsnptr); } } fclose(rbsnptr); }