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