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