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