1: #include < GL/glut.h > 2: #include < stdlib.h > 3: #include < stdio.h > 4: #include < string.h > 5: #include < math.h > 6: #include < iostream.h > 7: 8: #define Round(v) ((int)(v+0.5)) 9: #define MAX 800 10: #define MAX_FILE_LENGTH 256 11: 12: #define LOW_VALUE 0 13: #define HIGH_VALUE 255 14: 15: #define TRUE 1 16: #define FALSE 0 17: 18: /*cartesian coordinate type*/ 19: typedef struct {int x; 20: int y;}coord; 21: 22: /*RGB color struct*/ 23: typedef struct {float red; 24: float green; 25: float blue; 26: }RGB; 27: 28: /*RGB color struct*/ 29: typedef struct {int red; 30: int green; 31: int blue; 32: }RGB_INT; 33: 34: struct PGMstructure 35: { 36: int maxVal; 37: int width; 38: int height; 39: RGB_INT data[MAX][MAX]; 40: }; 41: 42: typedef struct PGMstructure PGMImage; 43: 44: /*Evil globals, but not do-able otherwise.*/ 45: static PGMImage *img_cur; 46: static PGMImage *img0; /*original*/ 47: static PGMImage *img1; /*current*/ 48: static PGMImage *img2; /*current*/ 49: static int HSIZE; 50: static int VSIZE; 51: static int MVAL; 52: 53: /**************Drawing funcitions************************************/ 54: /********************************************************************/ 55: 56: void setCPixel(int ix, int iy, RGB_INT color) 57: /*Same as setIPixel except that the last parameter is an RGB color*/ 58: { 59: RGB pixel_color; 60: float x = (ix*2.0)/HSIZE - 1.0; 61: float y = (iy*2.0)/VSIZE - 1.0; 62: 63: pixel_color.red = (float)color.red/(float)MVAL; 64: pixel_color.green = (float)color.green/(float)MVAL; 65: pixel_color.blue = (float)color.blue/(float)MVAL; 66: 67: glColor3f(pixel_color.red, pixel_color.green, pixel_color.blue); 68: 69: glBegin(GL_POINTS); 70: glVertex2f (x, y); 71: glEnd(); 72: } 73: 74: void pxlcpy(PGMImage *dest, int dest_row, int dest_col, 75: PGMImage *src, int src_row, int src_col) 76: { 77: /*make sure values are within bounds*/ 78: if(dest_col > 0 && dest_col < (*dest).width 79: && dest_row > 0 && dest_row < (*dest).height 80: && src_col > 0 && src_col < (*src).width 81: && src_row > 0 && src_row < (*src).height) 82: { 83: (*dest).data[dest_row][dest_col].red = 84: (*src).data[src_row][src_col].red; 85: 86: (*dest).data[dest_row][dest_col].green = 87: (*src).data[src_row][src_col].green; 88: 89: (*dest).data[dest_row][dest_col].blue = 90: (*src).data[src_row][src_col].blue; 91: } 92: } 93: 94: 95: /**********************File I/O functions*******************************/ 96: /***********************************************************************/ 97: 98: /*Gets an ascii color pgm image file (type P3).*/ 99: void getPGMfile (char filename[], PGMImage *img) 100: { 101: FILE *in_file; 102: char ch; 103: int row, col; 104: 105: in_file = fopen(filename, "r"); 106: if (in_file == NULL) 107: { 108: fprintf(stderr, "Error: Unable to open file %s\n\n", filename); 109: exit(8); 110: } 111: 112: printf("\nReading image file: %s", filename); 113: 114: do /* skip header identifier */ 115: ch = getc(in_file); 116: while (ch != '\n'); 117: 118: do /* skip comments lines */ 119: { 120: while (ch != '\n') ch = getc(in_file); /* flush to end of line */ 121: ch = getc(in_file); 122: } while (ch == '#'); 123: 124: fseek(in_file, -1, SEEK_CUR); /* backup one character */ 125: 126: fscanf(in_file,"%d", &((*img).width)); 127: fscanf(in_file,"%d", &((*img).height)); 128: fscanf(in_file,"%d", &((*img).maxVal)); 129: 130: printf("\n width = %d",(*img).width); 131: printf("\n height = %d",(*img).height); 132: printf("\n maxVal = %d",(*img).maxVal); 133: printf("\n"); 134: 135: if (((*img).width > MAX) || ((*img).height > MAX)) 136: { 137: printf("\n\n***ERROR - image too big for current image structure***\n\n"); 138: exit(0); 139: } 140: 141: for (row=(*img).height-1; row >=0; row--) 142: for (col=0; col< (*img).width; col++) 143: { 144: fscanf(in_file,"%d", &((*img).data[row][col].red) ); 145: fscanf(in_file,"%d", &((*img).data[row][col].green)); 146: fscanf(in_file,"%d", &((*img).data[row][col].blue)); 147: } 148: fclose(in_file); 149: printf("\nDone reading file.\n"); 150: } 151: 152: 153: void save(PGMImage *img) 154: { 155: int i, j, nr, nc, k; 156: int red, green, blue; 157: FILE *iop; 158: 159: nr = img- >height; 160: nc = img- >width; 161: 162: iop = fopen("image1.pgm", "w"); 163: fprintf(iop, "P3\n"); 164: fprintf(iop, "%d %d\n", nc, nr); 165: fprintf(iop, "255\n"); 166: 167: k = 1; 168: for(i = nr - 1; i >= 0; i--) 169: { 170: for(j = 0; j < nc; j++) 171: { 172: red = img- >data[i][j].red; 173: green = img- >data[i][j].green; 174: blue = img- >data[i][j].blue; 175: if(red < 0) 176: { 177: printf("IMG_WRITE: Found value %d at row %d col %d\n", red, i, j); 178: printf(" Setting red to zero\n"); 179: red = 0; 180: } 181: if(green < 0) 182: { 183: printf("IMG_WRITE: Found value %d at row %d col %d\n", green,i, j); 184: printf(" Setting green to zero\n"); 185: green = 0; 186: } 187: if(blue < 0) 188: { 189: printf("IMG_WRITE: Found value %d at row %d col %d\n", blue, i, j); 190: printf(" Setting green to zero\n"); 191: blue = 0; 192: } 193: if(red > 255) 194: { 195: printf("IMG_WRITE: Found value %d at row %d col %d\n", red, i, j); 196: printf(" Setting red to 255\n"); 197: red = 255; 198: } 199: if(green > 255) 200: { 201: printf("IMG_WRITE: Found value %d at row %d col %d\n", green,i, j); 202: printf(" Setting green to 255\n"); 203: green = 255; 204: } 205: if(blue > 255) 206: { 207: printf("IMG_WRITE: Found value %d at row %d col %d\n", blue, i, j); 208: printf(" Setting blue to 255\n"); 209: blue = 255; 210: } 211: 212: if(k % 10) 213: { 214: fprintf(iop, "%d ", red); 215: fprintf(iop, "%d ", green); 216: fprintf(iop, "%d ", blue); 217: } 218: else /*for newline*/ 219: { 220: fprintf(iop, "%d\n", red); 221: fprintf(iop, "%d\n", green); 222: fprintf(iop, "%d\n", blue); 223: } 224: k++; 225: } 226: } 227: fprintf(iop, "\n"); 228: fclose(iop); 229: } 230: 231: 232: /****Calculation & drawing functions of the image translations********** 233: ***********************************************************************/ 234: 235: 236: void showColor (PGMImage *img) 237: { 238: int row, col; /*y, x*/ 239: /*for (row=(*img).height-1; row >=0; row--) 240: for (col=0; col< (*img).width; col++) 241: { 242: 243: setCPixel(col, row, (*img).data[row][col]); 244: }*/ 245: 246: int i, j; /*loop counting: i = x, j = y*/ 247: int mid_width = ((*img).width / 2); 248: int mid_height = ((*img).height / 2); 249: 250: for(i = 0; i < mid_width / 2; i++) 251: { 252: for(j = 0; j < mid_height; j++) 253: { 254: /*inorder they are: 255: bottom left, bottom middle right, top left, top m right, 256: bottom middle left, bottom right, top middle left, top right.*/ 257: 258: setCPixel(i, j, (*img).data[j][i]); 259: setCPixel(i + mid_width, j, (*img).data[j][i + mid_width]); 260: setCPixel(i, j + mid_height, (*img).data[j + mid_height][i]); 261: setCPixel(i + mid_width, j + mid_height, 262: (*img).data[j + mid_height][i + mid_width]); 263: 264: setCPixel(mid_width - i - 1, j, 265: (*img).data[j][mid_width - i - 1]); 266: setCPixel((*img).width - i - 1, j, 267: (*img).data[j][(*img).width - i - 1]); 268: setCPixel(mid_width - i - 1, (*img).height - j - 1, 269: (*img).data[(*img).height - j - 1][mid_width - i - 1]); 270: setCPixel((*img).width - i - 1, (*img).height - j - 1, 271: (*img).data[(*img).height - j - 1][(*img).width - i - 1]); 272: } 273: } 274: 275: glFlush (); 276: } 277: 278: void camera_correction(PGMImage* new_img, PGMImage* org_img) 279: { 280: int row, col, img_row, img_col; /*loop counting*/ 281: 282: /*camera parameters*/ 283: float height = 30; /*height of camera in cm*/ 284: float gamma = 0, theta = .698; /*camera angles = 40 degrees in rad*/ 285: float aperture = 1.1968, alpha = .598; /*aperature = 2 * alpha*/ 286: 287: /*temporary varaibles*/ 288: float angular_height_corr; 289: float angular_side_corr; 290: int x_coord, y_coord; 291: 292: memset(new_img, 0, sizeof(PGMImage)); 293: (*new_img).height = (*org_img).height; 294: (*new_img).width = (*org_img).width; 295: (*new_img).maxVal = (*org_img).maxVal; 296: 297: for (row=(*org_img).height-1; row >=0; row--) 298: for (col=0; col< (*org_img).width; col++) 299: { 300: /*img_row -= (*org_img).height / 2; 301: img_col = col - (*org_img).width / 2;*/ 302: 303: angular_height_corr = 304: (theta - alpha) + col * (aperture / ((float)((*org_img).width) - 1)); 305: angular_side_corr = 306: (gamma - alpha) + row * (aperture / ((float)((*org_img).height) - 1)); 307: 308: angular_height_corr /= 2; 309: /*angular_side_corr /= 2;*/ 310: /*height *= 2;*/ 311: height = 150; 312: 313: x_coord = (int) 314: height * (1 / tan(angular_height_corr)) * cos(angular_side_corr); 315: y_coord = (int) 316: height * (1 / tan(angular_height_corr)) * sin(angular_side_corr); 317: 318: /*x_coord += (*org_img).width / 2;*/ 319: y_coord += (*org_img).height / 2; 320: 321: /*printf("org: (%d, %d) new: (%d, %d)\n\n", row, col, y_coord, x_coord);*/ 322: 323: pxlcpy(new_img, y_coord, x_coord, org_img, row, col); 324: } 325: } 326: 327: void new_corr(PGMImage* new_img, PGMImage* org_img) 328: { 329: /*i and j are the left half, k and l are the right half*/ 330: float i, k; /*loop counting*/ 331: int j, l, row; /*loop counting*/ 332: int old_i, old_k; 333: 334: float ins_s = 2; /*insert constant starting value*/ 335: float ins_k = ins_s; /*insert constant*/ 336: 337: /*The halfway marks in the width.*/ 338: int mid_width_left = ((*new_img).width / 2) - 1; 339: int mid_width_right = ((*new_img).width / 2); 340: 341: /*just to be thourough clear the memory and reset maxes*/ 342: memset(new_img, 0, sizeof(PGMImage)); 343: (*new_img).height = (*org_img).height; 344: (*new_img).width = (*org_img).width; 345: (*new_img).maxVal = (*org_img).maxVal; 346: 347: /*Loop through each row from top to bottom...*/ 348: for(row = ((*new_img).height - 1); row >= 0; row--) 349: { 350: /*...reset moire interference removal counter...*/ 351: old_i = ((*new_img).width / 2) - 1; 352: old_k = ((*new_img).width / 2); 353: 354: /*...so each half is ajusted to remove perspective effect...*/ 355: for(i = j = mid_width_left, k = l = mid_width_right 356: ; i >= 0, j >= 0, k < (*new_img).width, l < (*new_img).width 357: ; i -= ins_k, j--, k += ins_k, l++) 358: { 359: for(;old_i >= (int)i; old_i--) /*...in the left half...*/ 360: pxlcpy(new_img, row, old_i, org_img, row, j); 361: for(;old_k < = (int)k; old_k++) /*...in the right half.*/ 362: pxlcpy(new_img, row, old_k, org_img, row, l); 363: } 364: /*Move the new image x_coord pixel counter to next new image pixel*/ 365: ins_k -= ((ins_s - 1.0) / (*new_img).height); 366: } 367: } 368: 369: void color_to_gray(PGMImage* new_img, PGMImage* org_img) 370: { 371: int row, col; /*loop counting*/ 372: RGB_INT cur_pxl; /*current pixel*/ 373: 374: (*new_img).height = (*org_img).height; 375: (*new_img).width = (*org_img).width; 376: (*new_img).maxVal = (*org_img).maxVal; 377: 378: /*Starting with the top row...*/ 379: for(row = (*new_img).height - 1; row >= 0; row--) 380: for(col = 0; col < (*new_img).width - 1; col++) 381: { 382: cur_pxl = (*org_img).data[row][col]; /*more readable*/ 383: 384: /*convert each RGB to the average of the original*/ 385: (*new_img).data[row][col].red = 386: (cur_pxl.red + cur_pxl.green + cur_pxl.blue) / 3; 387: (*new_img).data[row][col].green = 388: (cur_pxl.red + cur_pxl.green + cur_pxl.blue) / 3; 389: (*new_img).data[row][col].blue = 390: (cur_pxl.red + cur_pxl.green + cur_pxl.blue) / 3; 391: } 392: } 393: 394: 395: /* ================================================================= 396: * Callback functions. 397: * 398: * color = displayed graphics in window 399: * menu = menu event handling 400: * keyboard = deyboard event handling 401: * ----------------------------------------------------------------- */ 402: void color(void) 403: { 404: /*glClear (GL_COLOR_BUFFER_BIT);*/ 405: 406: /* printf("\nDrawing Original image...\n");*/ 407: showColor(img_cur); 408: 409: /*glFlush();*/ 410: } 411: 412: #define RESTART 0 413: #define CAMERA_CORRECTION 1 414: #define X2_C_CORR 2 415: #define NEW_CORR 3 416: #define COLOR_TO_GRAY 4 417: 418: void menu(int selection) 419: { 420: if(selection == RESTART) 421: { 422: memcpy(img1, img0, sizeof(PGMImage)); 423: img_cur = img0; 424: } 425: if(selection == CAMERA_CORRECTION) 426: { 427: printf("Starting camera correction\n"); 428: camera_correction(img1, img0); 429: img_cur = img1; 430: } 431: if(selection == X2_C_CORR) 432: { 433: printf("Starting camera correction\n"); 434: camera_correction(img1, img0); 435: camera_correction(img2, img1); 436: img_cur = img2; 437: } 438: if(selection == NEW_CORR) 439: { 440: new_corr(img1, img0); 441: img_cur = img1; 442: } 443: if(selection == COLOR_TO_GRAY) 444: { 445: color_to_gray(img1, img0); 446: img_cur = img1; 447: } 448: /*glClear (GL_COLOR_BUFFER_BIT);*/ 449: showColor(img_cur); 450: glutPostRedisplay(); 451: } 452: 453: void keyboard(unsigned char key, int x, int y) 454: { 455: switch (key) 456: { 457: case 27: 458: exit(0); 459: break; 460: } 461: } 462: 463: /* ================================================================= 464: * init - initializes graphics viewport 465: * 466: * You should not have to change this function for the first few 467: * projects we have. It will become more important when we move to 468: * 3D graphics. 469: * ----------------------------------------------------------------- */ 470: void init (void) 471: { 472: 473: /* 474: * select clearing color - white 475: */ 476: glClearColor (1.0, 1.0, 1.0, 0.0); 477: 478: /* 479: * initialize viewport values 480: */ 481: glMatrixMode(GL_PROJECTION); 482: glLoadIdentity(); 483: glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); 484: 485: /*add menus*/ 486: glutCreateMenu(menu); 487: glutAddMenuEntry("Restart", RESTART); 488: glutAddMenuEntry("Camera Correction", CAMERA_CORRECTION); 489: glutAddMenuEntry("2x C. Corr.", X2_C_CORR); 490: glutAddMenuEntry("new corr", NEW_CORR); 491: glutAddMenuEntry("color to gray", COLOR_TO_GRAY); 492: glutAttachMenu(GLUT_RIGHT_BUTTON); 493: } 494: 495: int main(int argc, char** argv) 496: { 497: char PGMfileName[MAX_FILE_LENGTH]; 498: 499: int WindowID; 500: 501: int i; /*looping variable*/ 502: 503: /*parse the command line*/ 504: if(argc == 1) 505: { 506: printf("To few parameters.\n"); 507: printf("Usage: research < file.pgm >\n"); 508: exit(1); 509: } 510: else if(argc == 2) 511: strcpy(PGMfileName, argv[1]); 512: else 513: { 514: printf("To many parameters.\n"); 515: printf("Usage: research < file.pgm >\n"); 516: exit(1); 517: } 518: /* 519: * Read in image file. - note: sets our global values, too. 520: * ----------------------------------------------------------------- */ 521: 522: img0 = (PGMImage*) malloc(sizeof(PGMImage)); 523: getPGMfile(PGMfileName, img0); 524: HSIZE = (*img0).width; 525: VSIZE = (*img0).height; 526: MVAL = (*img0).maxVal; 527: 528: img_cur = img0; /*VERY IMPORTANT to set this*/ 529: 530: /*allocate memory for second image*/ 531: img1 = (PGMImage*) malloc(sizeof(PGMImage)); 532: memcpy(img1, img0, sizeof(PGMImage)); 533: /*(*img1).width = HSIZE; 534: (*img1).height = VSIZE; 535: (*img1).maxVal = 255;*/ 536: 537: img2 = (PGMImage*) malloc(sizeof(PGMImage)); 538: memcpy(img2, img0, sizeof(PGMImage)); 539: 540: /* 541: * Initialize the glut package. 542: * ----------------------------------------------------------------- */ 543: glutInit(&argc, argv); 544: glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); 545: /* 546: * Define a new window (its size, position and title). 547: * ----------------------------------------------------------------- */ 548: glutInitWindowSize (HSIZE, VSIZE); /*size*/ 549: glutInitWindowPosition (10, 10); /*position*/ 550: WindowID = glutCreateWindow (PGMfileName); /*title*/ 551: glutSetWindow(WindowID); 552: glutDisplayFunc(color); 553: 554: /* 555: * Call our init function to define viewing parameters. 556: * ----------------------------------------------------------------- */ 557: init (); 558: 559: glutKeyboardFunc(keyboard); 560: glutMainLoop(); 561: 562: /* 563: * When we reach here, we've left the event loop and are ready to 564: * exit. 565: * ----------------------------------------------------------------- */ 566: return 0; 567: } 568: 569: 570: 571: 572: 573: 574: 575: 576: 577: 578: 579: 580: