1: #include < GL/glut.h > 2: #include < stdlib.h > 3: #include < stdio.h > 4: #include < string.h > 5: #include < math.h > 6: 7: #define Round(v) ((int)(v+0.5)) 8: #define MAX 800 9: #define MAX_FILE_LENGTH 256 10: 11: #define LOW_VALUE 0 12: #define HIGH_VALUE 255 13: 14: #define TRUE 1 15: #define FALSE 0 16: 17: /*#ifdef __STDC__ 18: typedef int bool; 19: #endif*/ 20: 21: /*cartesian coordinate type*/ 22: typedef struct {int x; 23: int y;}coord; 24: 25: /*RGB color struct with floats*/ 26: /*typedef struct {float red; 27: float green; 28: float blue; 29: }RGB; 30: */ 31: /*RGB color struct with ints*/ 32: typedef struct {int red; 33: int green; 34: int blue; 35: }RGB_INT; 36: 37: /*number of chain codes stored*/ 38: #define MAX_CHAINS 10 39: 40: /*These constant values are the chain code directions*/ 41: #define NONE -1 42: #define EAST 0 43: #define NORTHEAST 1 44: #define NORTH 2 45: #define NORTHWEST 3 46: #define WEST 4 47: #define SOUTHWEST 5 48: #define SOUTH 6 49: #define SOUTHEAST 7 50: 51: typedef struct chainCode* chain_t; 52: typedef struct chainCode 53: { 54: chain_t prev; 55: int code; 56: coord location; /*absolute pixel location for starting point*/ 57: chain_t next; 58: }; 59: 60: struct PGMstructure 61: { 62: int maxVal; 63: int width; 64: int height; 65: RGB_INT data[MAX][MAX]; 66: }; 67: 68: typedef struct PGMstructure PGMImage; 69: 70: /*Evil globals, but not do-able otherwise.*/ 71: static PGMImage *img_cur; 72: static PGMImage *img0; /*original*/ 73: static PGMImage *img1; /*current*/ 74: static PGMImage *img2; /*current*/ 75: static int HSIZE; 76: static int VSIZE; 77: static int MVAL; 78: 79: 80: 81: 82: /**************Drawing funcitions************************************/ 83: /********************************************************************/ 84: 85: void setCPixel(int ix, int iy, RGB_INT color) 86: /*Same as setIPixel except that the last parameter is an RGB color*/ 87: { 88: float x = (ix*2.0)/HSIZE - 1.0; 89: float y = (iy*2.0)/VSIZE - 1.0; 90: 91: float red = (float)color.red/(float)MVAL; 92: float green = (float)color.green/(float)MVAL; 93: float blue = (float)color.blue/(float)MVAL; 94: 95: glColor3f(red, green, blue); 96: 97: glBegin(GL_POINTS); 98: glVertex2f (x, y); 99: glEnd(); 100: } 101: 102: void setCLines(int ix1, int iy1, int ix2, int iy2, RGB_INT color) 103: /*Similar as setIPixel except that this one draws a line between the first set 104: of points given and the second set in the RGB color specified*/ 105: { 106: float x1 = (ix1*2.0)/HSIZE - 1.0; 107: float y1 = (iy1*2.0)/VSIZE - 1.0; 108: float x2 = (ix2*2.0)/HSIZE - 1.0; 109: float y2 = (iy2*2.0)/VSIZE - 1.0; 110: 111: float red = (float)color.red/(float)MVAL; 112: float green = (float)color.green/(float)MVAL; 113: float blue = (float)color.blue/(float)MVAL; 114: 115: glColor3f(red, green, blue); 116: 117: glBegin(GL_LINES); 118: glVertex2f (x1, y1); 119: glVertex2f (x2, y2); 120: glEnd(); 121: } 122: 123: void setCRect(int ix1, int iy1, int ix2, int iy2, RGB_INT color) 124: /*Similar as setIPixel except that this one draws a line between the first set 125: of points given and the second set in the RGB color specified*/ 126: { 127: float x1 = (ix1*2.0)/HSIZE - 1.0; 128: float y1 = (iy1*2.0)/VSIZE - 1.0; 129: float x2 = (ix2*2.0)/HSIZE - 1.0; 130: float y2 = (iy2*2.0)/VSIZE - 1.0; 131: 132: float red = (float)color.red/(float)MVAL; 133: float green = (float)color.green/(float)MVAL; 134: float blue = (float)color.blue/(float)MVAL; 135: 136: glColor3f(red, green, blue); 137: 138: glBegin(GL_POLYGON); 139: glVertex2f (x1, y1); 140: glVertex2f (x1, y2); 141: glVertex2f (x2, y2); 142: glVertex2f (x2, y1); 143: glEnd(); 144: } 145: 146: void pxlcpy(PGMImage *dest, int dest_row, int dest_col, 147: PGMImage *src, int src_row, int src_col) 148: { 149: /*make sure values are within bounds*/ 150: if(dest_col > 0 && dest_col < (*dest).width 151: && dest_row > 0 && dest_row < (*dest).height 152: && src_col > 0 && src_col < (*src).width 153: && src_row > 0 && src_row < (*src).height) 154: { 155: (*dest).data[dest_row][dest_col].red = 156: (*src).data[src_row][src_col].red; 157: 158: (*dest).data[dest_row][dest_col].green = 159: (*src).data[src_row][src_col].green; 160: 161: (*dest).data[dest_row][dest_col].blue = 162: (*src).data[src_row][src_col].blue; 163: } 164: } 165: 166: int rgb_avg(RGB_INT cur_pxl) 167: { 168: /*convert each RGB to the average of the original*/ 169: return ((cur_pxl.red + cur_pxl.green + cur_pxl.blue) / 3); 170: } 171: 172: /*1st: pixel one of type RGB_INT 173: 2nd: pixel one of type RGB_INT 174: 3rd: differnce allowed to be considered "equal" or close enough*/ 175: int pxlcmp (RGB_INT pxl1, RGB_INT pxl2, int range) 176: { 177: return ((abs((rgb_avg(pxl1) - rgb_avg(pxl2)))) < range); 178: } 179: 180: /*================================================================= 181: * drawString - outputs a string of characters to the graphics port 182: * 183: * x, y: defines the starting location to draw the text 184: * note: this point is the lower left anchor of 185: * the first character - a character's decending 186: * portion would be drawn below this point. 187: * theFont: points to the glut font to be used 188: * theString: holds the string to be output -- up to 255 ch 189: * ----------------------------------------------------------------- */ 190: void drawString(int ix, int iy, void *theFont, char theString[256]) 191: { 192: float x = (ix*2.0)/HSIZE - 1.0; 193: float y = (iy*2.0)/VSIZE - 1.0; 194: int i; 195: glRasterPos2f(x, y); 196: for (i = 0; theString[i] != '\0'; i++) /* draw the chars one at a time */ 197: glutBitmapCharacter(theFont, theString[i]); 198: } 199: 200: /******CHAIN CODE************************************************ 201: ****************************************************************/ 202: 203: /*returns NONE if the chain code loops around itself, otherwise false*/ 204: int checkCode(chainCode* beginning, int x_current, int y_current, int x_check, 205: int y_check, int dir) 206: { 207: chainCode* currentNode = beginning; 208: 209: while(currentNode && currentNode- >next) 210: { 211: if((currentNode- >location.x == x_current) && 212: (currentNode- >location.y == y_current) && 213: (currentNode- >code == dir) && 214: (currentNode- >next- >location.x == x_check) && 215: (currentNode- >next- >location.y == y_check)) 216: return NONE; 217: else 218: currentNode = currentNode- >next; 219: } 220: return FALSE; 221: 222: } 223: 224: RGB_INT chainColor = {0, 0, 255}; 225: 226: /*This function is the intermediate function call during the recursion of the 227: chain code calculation. 228: Preconditions: 229: 1st parameter: integer value containing the current direction code. 230: 2nd parameter: integer value containing the potentially new direction code. 231: 3rd parameter: integer value containing the current x coordinate. 232: 4th parameter: integer value containing the current y coordinate. 233: 5th parameter: pointer to the linked list of the chain code. 234: 6th parameter: pointer to the pgm image being used. 235: Postconditions: The pixel is drawn and if the checked pixel is a boarder pixel 236: true is returned, otherwise false is returned.*/ 237: int checkThings(int *dir, int next, int x_current, int y_current, int x_check, 238: int y_check, chainCode **theChain, PGMImage *img, chainCode **beginning) 239: { 240: chainCode *temp; 241: 242: /*check for being in bounds*/ 243: if((x_check < 0) || (y_check < 0) || (x_check >= (*img).width) || 244: (y_check >= (*img).height)) 245: return FALSE; 246: 247: /*test condition for the end.*/ 248: else if(checkCode(*beginning, x_current, y_current, x_check, y_check, 249: *dir) == NONE) 250: { 251: *dir = NONE; 252: return FALSE; 253: } 254: 255: /*tests if the next pixel is a boundry pixel. If so does stuff*/ 256: if(pxlcmp((*img).data[y_current][x_current], 257: (*img).data[y_check][x_check], 100)) 258: { 259: setCPixel(x_check, y_check, chainColor); 260: glFlush(); 261: *dir = next; 262: temp = (chain_t)malloc(sizeof(chainCode)); 263: temp- >next = NULL; 264: temp- >code = *dir; 265: temp- >location.x = x_check; 266: temp- >location.y = y_check; 267: temp- >prev = *theChain; 268: if(*theChain) 269: (*theChain)- >next = temp; /*now this is a good thing to set.*/ 270: *theChain = temp; /*advance one*/ 271: 272: if(*beginning == NULL) 273: *beginning = *theChain;/*set this for the first node in the list once*/ 274: return TRUE; 275: } 276: return FALSE; 277: } 278: 279: /*determines the chain code for a starting pixel*/ 280: /*this chain code uses 8 connectivity*/ 281: /*Note: There are many different coordinate systems at work in this function.*/ 282: /*The (*img).data[][] are column major and have are therefore [y][x] or [j][i]*//* This is also asuming (0,0) is bottom left, where the other code assumes 283: /* top left is (0, 0). If it looks strange, look harder!!!*/ 284: /*Preconditions: 285: 1st parameter: pointer to the pgm image being used. 286: 2nd parameter: integer value containing the current x coordinate. 287: 3rd parameter: integer value containing the current y coordinate. 288: 4th parameter: integer value containing the current direction code. 289: 5th parameter: pointer to the linked list of the chain code. 290: 6th parameter: pointer to the linked list of the chain code.*/ 291: /*This function assumes the (0, 0) point is in the lower left*/ 292: 293: int chaincode(PGMImage *img, int x, int y, int dir, chainCode** theChain, 294: chainCode** beginning) 295: { 296: int i; /*loop counting*/ 297: int initial, next, finished; 298: 299: if(dir % 2) /*if dir is odd*/ 300: initial = (dir + 6) % 8; 301: else /*if dir is even*/ 302: initial = (dir + 7) % 8; 303: 304: next = initial; /*set the next direction to search*/ 305: /*printf("next: %d x: %d y: %d\n", next, x, y); */ 306: for(i = 0; i < 8; i++) 307: { 308: if(next == EAST) 309: { 310: if(checkThings(&dir, EAST, x, y, x + 1, y, theChain, img, beginning)) 311: finished = chaincode(img, x + 1, y, dir, theChain, beginning); 312: } 313: else if(next == NORTHEAST) 314: { 315: 316: if(checkThings(&dir, NORTHEAST, x, y, x + 1, y + 1, theChain, img, 317: beginning)) 318: finished = chaincode(img, x + 1, y + 1, dir, theChain, beginning); 319: } 320: else if(next == NORTH) 321: { 322: if(checkThings(&dir, NORTH, x, y, x, y + 1, theChain, img, 323: beginning)) 324: finished = chaincode(img, x, y + 1, dir, theChain, beginning); 325: } 326: else if(next == NORTHWEST) 327: { 328: if(checkThings(&dir, NORTHWEST, x, y, x - 1, y + 1, theChain, img, 329: beginning)) 330: finished = chaincode(img, x - 1, y + 1, dir, theChain, beginning); 331: } 332: else if(next == WEST) 333: { 334: if(checkThings(&dir, WEST, x, y, x - 1, y, theChain, img, beginning)) 335: finished = chaincode(img, x - 1, y, dir, theChain, beginning); 336: } 337: else if(next == SOUTHWEST) 338: { 339: if(checkThings(&dir, SOUTHWEST, x, y, x - 1, y - 1, theChain, img, 340: beginning)) 341: finished = chaincode(img, x - 1, y - 1, dir, theChain, beginning); 342: } 343: else if(next == SOUTH) 344: { 345: if(checkThings(&dir, SOUTH, x, y, x, y - 1, theChain, img,beginning)) 346: finished = chaincode(img, x, y - 1, dir, theChain, beginning); 347: } 348: else if(next == SOUTHEAST) 349: { 350: if(checkThings(&dir, SOUTHEAST, x, y, x + 1, y - 1, theChain, img, 351: beginning)) 352: finished = chaincode(img, x + 1, y - 1, dir, theChain, beginning); 353: } 354: 355: /*if the next chaincode function in the recursion or the current state 356: is the final state of the the chain code; recursively returns DONE 357: back through all the levels to stop the chain code.*/ 358: if(dir == NONE || finished == NONE) 359: return NONE; 360: /*set next for next iteration*/ 361: next = (next + 1) % 8; 362: } 363: 364: } 365: 366: /*returns true if the point is already in one of the chains, false otherwise*/ 367: int alreadyFound(int initThreashFlag, int i, int j, PGMImage* img, 368: chainCode** found, int count) 369: { 370: int k; 371: chainCode* temp; 372: /*this if statement determines if a pixel is not the background*/ 373: if(initThreashFlag < rgb_avg((*img).data[j][i])) /*collumn major*/ 374: { 375: /*Now search to determine if the pixel has been found already*/ 376: for(k = 0; k < = count; k++) 377: { 378: temp = (found[k]); 379: while(temp) 380: {/* if point has already been found*/ 381: if((temp- >location.x == i) && (temp- >location.y == j)) 382: { 383: j = 0; /*does this work?*/ 384: return TRUE; 385: break; 386: } 387: temp = temp- >next; 388: } 389: } 390: } 391: return FALSE; 392: } 393: 394: /*saves a chain code to file. Was usefull during debuging now is just 395: a cool thing to leave in*/ 396: /*1st: pointer to beginning of a chaincode 397: 2nd: the index of the chain code for destiqushing the 'chain' files*/ 398: void saveChainCode(chainCode* saveChain, int count) 399: { 400: chainCode* temp = saveChain; 401: char filename[12]; 402: FILE* outfile; 403: sprintf(filename, "chain%d", count); 404: outfile = fopen(filename, "w"); /*output file for chaincode*/ 405: printf("Writing chain code to file %s.\n", filename); 406: 407: while(temp) 408: { 409: 410: fprintf(outfile, "%d %d %d\n",temp- >location.x,temp- >location.y, 411: temp- >code); 412: temp = temp- >next; 413: } 414: fclose(outfile); 415: } 416: 417: chainCode** showChain(PGMImage *original) 418: { 419: int i, j; /*loop counting*/ 420: int initThreashFlag = 128, foundFlag = TRUE; 421: RGB_INT /*chainColor = {255, 0, 255},*/ tempColor = {255, 0, 0}; 422: chainCode** beginning, *chain = NULL, *temp, *next_tmep, *temp_loop; 423: beginning = (chainCode**) malloc (MAX_CHAINS * sizeof(chainCode*)); 424: int count = 0; /*array index holder*/ 425: /*Need a temporary threasholded image*/ 426: /*PGMImage *threashed = (PGMImage*) malloc(sizeof(PGMImage)); 427: */ 428: glPointSize(4); /*make points more visible*/ 429: 430: /*showThreashold(original, threashed);*/ 431: 432: /*Use starting pixel as defualt. This is partially based on the fact that 433: most likely a corner will be background and not an object.*/ 434: /*the image assumes that (0, 0) is in the bottom left, I assume that 435: (0, 0) is in the upper left. This is handled here.*/ 436: /*initThreashFlag = (*threashed).data[(*threashed).height - 1][0];*/ 437: 438: for(i = 0; i < 10; i++) beginning[i] = NULL;/*initailize pointer array.*/ 439: 440: /*search image until a pixel is found with threasholded value of the 441: object. i & j will then contain the starting coordinate.*/ 442: for(i = 0; i < (*original).width; i++) 443: { 444: for(j = (*original).height - 1; j >= 0; j--) 445: { 446: /*skip to the next iteration if pixel isn't "good" enough*/ 447: if(rgb_avg((*original).data[j][i]) < initThreashFlag) 448: { 449: continue; 450: } 451: /*skip to the next iteration, which will be at the top of the next 452: collumn*/ 453: else if(alreadyFound(initThreashFlag, i, j, original, beginning, 454: count)) 455: { 456: j = 0; /*reseting to make this the last iteration without reseting 457: search to the top of next collumn*/ 458: continue; 459: } 460: else 461: { 462: /*printf("chaincode: %d\n", count);*/ 463: /*printf("The starting coordinate is (x, y): (%d, %d)\n", i, j);*/ 464: chain = NULL; /*reset this to seperate the chaincodes*/ 465: 466: chainColor.blue = (128 + 10 * count) * (count % 2); 467: chainColor.green =(128 + 10 * count) * (count % 3); 468: chainColor.red =(128 + 10 * count); 469: /*find the chaincode for the current starting pixel*/ 470: chaincode(original, i, j, SOUTHEAST, &chain, &beginning[count]); 471: 472: if(beginning[count] != NULL) /*avoid writing zero length chains*/ 473: { 474: saveChainCode(beginning[count], count); 475: count++; /*advance the beginning counter*/ 476: } 477: 478: /*force end of loops, leaving code when finished looping 479: to still execute*/ 480: if(count >= MAX_CHAINS) 481: i = (*original).width; 482: 483: j = 0; /*reset search to start at top on next pass. This the 484: setting for stopping condition for the current j loop.*/ 485: break; /*Quick fix?*/ 486: } 487: } 488: } 489: printf("Done finding chain code(s). %d were found.\n", count); 490: return beginning; 491: } 492: 493: 494: /**********************File I/O functions*******************************/ 495: /***********************************************************************/ 496: 497: /*Gets an ascii color pgm image file (type P3).*/ 498: void getPGMfile (char filename[], PGMImage *img) 499: { 500: FILE *in_file; 501: char ch; 502: int row, col; 503: 504: in_file = fopen(filename, "r"); 505: if (in_file == NULL) 506: { 507: fprintf(stderr, "Error: Unable to open file %s\n\n", filename); 508: exit(8); 509: } 510: 511: printf("\nReading image file: %s", filename); 512: 513: do /* skip header identifier */ 514: ch = getc(in_file); 515: while (ch != '\n'); 516: 517: do /* skip comments lines */ 518: { 519: while (ch != '\n') ch = getc(in_file); /* flush to end of line */ 520: ch = getc(in_file); 521: } while (ch == '#'); 522: 523: fseek(in_file, -1, SEEK_CUR); /* backup one character */ 524: 525: fscanf(in_file,"%d", &((*img).width)); 526: fscanf(in_file,"%d", &((*img).height)); 527: fscanf(in_file,"%d", &((*img).maxVal)); 528: 529: printf("\n width = %d",(*img).width); 530: printf("\n height = %d",(*img).height); 531: printf("\n maxVal = %d",(*img).maxVal); 532: printf("\n"); 533: 534: if (((*img).width > MAX) || ((*img).height > MAX)) 535: { 536: printf("\n\n***ERROR - image too big for current image structure***\n\n"); 537: exit(0); 538: } 539: 540: for (row=(*img).height-1; row >=0; row--) 541: for (col=0; col< (*img).width; col++) 542: { 543: fscanf(in_file,"%d", &((*img).data[row][col].red) ); 544: fscanf(in_file,"%d", &((*img).data[row][col].green)); 545: fscanf(in_file,"%d", &((*img).data[row][col].blue)); 546: } 547: fclose(in_file); 548: printf("\nDone reading file.\n"); 549: } 550: 551: 552: void save(PGMImage *img) 553: { 554: int i, j, nr, nc, k; 555: int red, green, blue; 556: FILE *iop; 557: 558: nr = img- >height; 559: nc = img- >width; 560: 561: iop = fopen("image1.pgm", "w"); 562: fprintf(iop, "P3\n"); 563: fprintf(iop, "%d %d\n", nc, nr); 564: fprintf(iop, "255\n"); 565: 566: k = 1; 567: for(i = nr - 1; i >= 0; i--) 568: { 569: for(j = 0; j < nc; j++) 570: { 571: red = img- >data[i][j].red; 572: green = img- >data[i][j].green; 573: blue = img- >data[i][j].blue; 574: if(red < 0) 575: { 576: printf("IMG_WRITE: Found value %d at row %d col %d\n", red, i, j); 577: printf(" Setting red to zero\n"); 578: red = 0; 579: } 580: if(green < 0) 581: { 582: printf("IMG_WRITE: Found value %d at row %d col %d\n", green,i, j); 583: printf(" Setting green to zero\n"); 584: green = 0; 585: } 586: if(blue < 0) 587: { 588: printf("IMG_WRITE: Found value %d at row %d col %d\n", blue, i, j); 589: printf(" Setting green to zero\n"); 590: blue = 0; 591: } 592: if(red > 255) 593: { 594: printf("IMG_WRITE: Found value %d at row %d col %d\n", red, i, j); 595: printf(" Setting red to 255\n"); 596: red = 255; 597: } 598: if(green > 255) 599: { 600: printf("IMG_WRITE: Found value %d at row %d col %d\n", green,i, j); 601: printf(" Setting green to 255\n"); 602: green = 255; 603: } 604: if(blue > 255) 605: { 606: printf("IMG_WRITE: Found value %d at row %d col %d\n", blue, i, j); 607: printf(" Setting blue to 255\n"); 608: blue = 255; 609: } 610: 611: if(k % 10) 612: { 613: fprintf(iop, "%d ", red); 614: fprintf(iop, "%d ", green); 615: fprintf(iop, "%d ", blue); 616: } 617: else /*for newline*/ 618: { 619: fprintf(iop, "%d\n", red); 620: fprintf(iop, "%d\n", green); 621: fprintf(iop, "%d\n", blue); 622: } 623: k++; 624: } 625: } 626: fprintf(iop, "\n"); 627: fclose(iop); 628: } 629: 630: 631: 632: 633: /****Calculation & drawing functions of the image translations********** 634: ***********************************************************************/ 635: 636: 637: void showColor (PGMImage *img) 638: { 639: int row, col; /*y, x*/ 640: /*for (row=(*img).height-1; row >=0; row--) 641: for (col=0; col< (*img).width; col++) 642: { 643: 644: setCPixel(col, row, (*img).data[row][col]); 645: }*/ 646: 647: int i, j; /*loop counting: i = x, j = y*/ 648: int mid_width = ((*img).width / 2); 649: int mid_height = ((*img).height / 2); 650: 651: for(i = 0; i < mid_width / 2; i++) 652: { 653: for(j = 0; j < mid_height; j++) 654: { 655: /*inorder they are: 656: bottom left, bottom middle right, top left, top m right, 657: bottom middle left, bottom right, top middle left, top right.*/ 658: 659: setCPixel(i, j, (*img).data[j][i]); 660: setCPixel(i + mid_width, j, (*img).data[j][i + mid_width]); 661: setCPixel(i, j + mid_height, (*img).data[j + mid_height][i]); 662: setCPixel(i + mid_width, j + mid_height, 663: (*img).data[j + mid_height][i + mid_width]); 664: 665: setCPixel(mid_width - i - 1, j, 666: (*img).data[j][mid_width - i - 1]); 667: setCPixel((*img).width - i - 1, j, 668: (*img).data[j][(*img).width - i - 1]); 669: setCPixel(mid_width - i - 1, (*img).height - j - 1, 670: (*img).data[(*img).height - j - 1][mid_width - i - 1]); 671: setCPixel((*img).width - i - 1, (*img).height - j - 1, 672: (*img).data[(*img).height - j - 1][(*img).width - i - 1]); 673: } 674: } 675: glFlush(); 676: } 677: 678: void camera_correction(PGMImage* new_img, PGMImage* org_img) 679: { 680: int row, col, img_row, img_col; /*loop counting*/ 681: 682: /*camera parameters*/ 683: float height = 30; /*height of camera in cm*/ 684: float gamma = 0, theta = .698; /*camera angles = 40 degrees in rad*/ 685: float aperture = 1.1968, alpha = .598; /*aperature = 2 * alpha*/ 686: 687: /*temporary varaibles*/ 688: float angular_height_corr; 689: float angular_side_corr; 690: int x_coord, y_coord; 691: 692: memset(new_img, 0, sizeof(PGMImage)); 693: (*new_img).height = (*org_img).height; 694: (*new_img).width = (*org_img).width; 695: (*new_img).maxVal = (*org_img).maxVal; 696: 697: for (row=(*org_img).height-1; row >=0; row--) 698: for (col=0; col< (*org_img).width; col++) 699: { 700: /*img_row -= (*org_img).height / 2; 701: img_col = col - (*org_img).width / 2;*/ 702: 703: angular_height_corr = 704: (theta - alpha) + col * (aperture / ((float)((*org_img).width) - 1)); 705: angular_side_corr = 706: (gamma - alpha) + row * (aperture / ((float)((*org_img).height) - 1)); 707: 708: angular_height_corr /= 2; 709: /*angular_side_corr /= 2;*/ 710: /*height *= 2;*/ 711: height = 150; 712: 713: x_coord = (int) 714: height * (1 / tan(angular_height_corr)) * cos(angular_side_corr); 715: y_coord = (int) 716: height * (1 / tan(angular_height_corr)) * sin(angular_side_corr); 717: 718: /*x_coord += (*org_img).width / 2;*/ 719: y_coord += (*org_img).height / 2; 720: 721: /*printf("org: (%d, %d) new: (%d, %d)\n\n", row, col, y_coord, x_coord);*/ 722: 723: pxlcpy(new_img, y_coord, x_coord, org_img, row, col); 724: } 725: } 726: 727: void new_corr(PGMImage* new_img, PGMImage* org_img) 728: { 729: /*i and j are the left half, k and l are the right half*/ 730: float i, k; /*loop counting*/ 731: int j, l, row; /*loop counting*/ 732: int old_i, old_k; 733: 734: float ins_s = 2; /*insert constant starting value*/ 735: float ins_k = ins_s; /*insert constant*/ 736: 737: /*The halfway marks in the width.*/ 738: int mid_width_left = ((*new_img).width / 2) - 1; 739: int mid_width_right = ((*new_img).width / 2); 740: 741: /*just to be thourough clear the memory and reset maxes*/ 742: memset(new_img, 0, sizeof(PGMImage)); 743: (*new_img).height = (*org_img).height; 744: (*new_img).width = (*org_img).width; 745: (*new_img).maxVal = (*org_img).maxVal; 746: 747: /*Loop through each row from top to bottom...*/ 748: for(row = ((*new_img).height - 1); row >= 0; row--) 749: { 750: /*...reset moire interference removal counter...*/ 751: old_i = ((*new_img).width / 2) - 1; 752: old_k = ((*new_img).width / 2); 753: 754: /*...so each half is ajusted to remove perspective effect...*/ 755: for(i = j = mid_width_left, k = l = mid_width_right 756: ; i >= 0, j >= 0, k < (*new_img).width, l < (*new_img).width 757: ; i -= ins_k, j--, k += ins_k, l++) 758: { 759: for(;old_i >= (int)i; old_i--) /*...in the left half...*/ 760: pxlcpy(new_img, row, old_i, org_img, row, j); 761: for(;old_k < = (int)k; old_k++) /*...in the right half.*/ 762: pxlcpy(new_img, row, old_k, org_img, row, l); 763: } 764: /*Move the new image x_coord pixel counter to next new image pixel*/ 765: ins_k -= ((ins_s - 1.0) / (*new_img).height); 766: } 767: } 768: 769: void color_to_gray(PGMImage* new_img, PGMImage* org_img) 770: { 771: int row, col; /*loop counting*/ 772: RGB_INT cur_pxl; /*current pixel*/ 773: 774: (*new_img).height = (*org_img).height; 775: (*new_img).width = (*org_img).width; 776: (*new_img).maxVal = (*org_img).maxVal; 777: 778: /*Starting with the top row...*/ 779: for(row = (*new_img).height - 1; row >= 0; row--) 780: for(col = 0; col < (*new_img).width - 1; col++) 781: { 782: cur_pxl = (*org_img).data[row][col]; /*more readable*/ 783: 784: /*convert each RGB to the average of the original*/ 785: (*new_img).data[row][col].red = rgb_avg(cur_pxl); 786: (*new_img).data[row][col].green = rgb_avg(cur_pxl); 787: (*new_img).data[row][col].blue = rgb_avg(cur_pxl); 788: } 789: } 790: 791: void moravec(PGMImage* new_img, PGMImage* org_img) 792: { 793: int row, col; /*loop counting*/ 794: int i, j, k, l; /*Sanka, Hlavac & Boyle; p. 97 f. 4.73*/ 795: int running_sum; 796: float K = .5; /*.125 according to org. formula, but .5 is brighter*/ 797: int max_val = 0, row_max, col_max; /* max porportion value in image*/ 798: 799: memset(new_img, 0, sizeof(PGMImage)); 800: (*new_img).height = (*org_img).height; 801: (*new_img).width = (*org_img).width; 802: (*new_img).maxVal = (*org_img).maxVal; 803: 804: /*starting at the top row*/ 805: for(row = (*new_img).height - 1 - 1; row > 0; row--) 806: for(col = 1; col < (*new_img).width - 1; col++) /*left col start*/ 807: { 808: i = row; 809: j = col; 810: running_sum = 0; 811: 812: /*Sanka, Hlavac & Boyle; p. 97 f. 4.73*/ 813: for(k = i - 1; k < = i + 1; k++) /*row*/ 814: for(l = j - 1; l < = j + 1; l++) /*column*/ 815: running_sum += abs(rgb_avg((*org_img).data[k][l]) - 816: rgb_avg((*org_img).data[i][j])); 817: 818: /*assign the new pixel value*/ 819: (*new_img).data[row][col].red = (int)(K * running_sum); 820: (*new_img).data[row][col].green = (int)(K * running_sum); 821: (*new_img).data[row][col].blue = (int)(K * running_sum); 822: } 823: } 824: 825: void detect_corners(PGMImage* org_img) 826: { 827: chainCode **chain_codes; 828: 829: chain_codes = showChain(org_img); 830: } 831: 832: /* ================================================================= 833: * Callback functions. 834: * 835: * color = displayed graphics in window 836: * menu = menu event handling 837: * keyboard = deyboard event handling 838: * ----------------------------------------------------------------- */ 839: void color(void) 840: { 841: /*glClear (GL_COLOR_BUFFER_BIT);*/ 842: 843: /* printf("\nDrawing Original image...\n");*/ 844: showColor(img_cur); 845: 846: /*glFlush();*/ 847: } 848: 849: #define RESTART 0 850: #define CAMERA_CORRECTION 1 851: #define X2_C_CORR 2 852: #define NEW_CORR 3 853: #define COLOR_TO_GRAY 4 854: #define MORAVEC 5 855: #define CORNERS 6 856: 857: void menu(int selection) 858: { 859: if(selection == RESTART) 860: { 861: memcpy(img1, img0, sizeof(PGMImage)); 862: img_cur = img0; 863: } 864: if(selection == CAMERA_CORRECTION) 865: { 866: printf("Starting camera correction\n"); 867: camera_correction(img1, img0); 868: img_cur = img1; 869: } 870: if(selection == X2_C_CORR) 871: { 872: printf("Starting camera correction\n"); 873: camera_correction(img1, img0); 874: camera_correction(img2, img1); 875: img_cur = img2; 876: } 877: if(selection == NEW_CORR) 878: { 879: new_corr(img1, img0); 880: img_cur = img1; 881: } 882: if(selection == COLOR_TO_GRAY) 883: { 884: color_to_gray(img1, img0); 885: img_cur = img1; 886: } 887: if(selection == MORAVEC) 888: { 889: moravec(img1, img0); 890: img_cur = img1; 891: } 892: if(selection == CORNERS) 893: { 894: new_corr(img1, img0); 895: /*moravec(img2, img1);*/ 896: showColor(img1); 897: detect_corners(img1); 898: img_cur = img1; 899: return; 900: } 901: /*glClear (GL_COLOR_BUFFER_BIT);*/ 902: showColor(img_cur); 903: glutPostRedisplay(); 904: } 905: 906: void keyboard(unsigned char key, int x, int y) 907: { 908: switch (key) 909: { 910: case 27: 911: exit(0); 912: break; 913: } 914: } 915: 916: void mouse(int button, int state, int x, int y) 917: { 918: char temp[25]; 919: RGB_INT erase = {0, 0, 0}; 920: 921: if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) 922: { 923: sprintf(temp, "(x, y): (%d, %d)\n", x, VSIZE - y); 924: setCRect(0, 0, 100, 12, erase); 925: glColor3f(1.0, 0.0, 0.0); 926: drawString(0, 0, GLUT_BITMAP_TIMES_ROMAN_10, temp); 927: glFlush(); 928: } 929: } 930: 931: /* ================================================================= 932: * init - initializes graphics viewport 933: * 934: * You should not have to change this function for the first few 935: * projects we have. It will become more important when we move to 936: * 3D graphics. 937: * ----------------------------------------------------------------- */ 938: void init (void) 939: { 940: 941: /* 942: * select clearing color - white 943: */ 944: glClearColor (1.0, 1.0, 1.0, 0.0); 945: 946: /* 947: * initialize viewport values 948: */ 949: glMatrixMode(GL_PROJECTION); 950: glLoadIdentity(); 951: glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); 952: 953: /*add menus*/ 954: glutCreateMenu(menu); 955: glutAddMenuEntry("Restart", RESTART); 956: glutAddMenuEntry("Camera Correction", CAMERA_CORRECTION); 957: glutAddMenuEntry("2x C. Corr.", X2_C_CORR); 958: glutAddMenuEntry("new corr", NEW_CORR); 959: glutAddMenuEntry("color to gray", COLOR_TO_GRAY); 960: glutAddMenuEntry("moravec", MORAVEC); 961: glutAddMenuEntry("corners", CORNERS); 962: glutAttachMenu(GLUT_RIGHT_BUTTON); 963: } 964: 965: int main(int argc, char** argv) 966: { 967: char PGMfileName[MAX_FILE_LENGTH]; 968: 969: int WindowID; 970: 971: int i; /*looping variable*/ 972: 973: /*parse the command line*/ 974: if(argc == 1) 975: { 976: printf("To few parameters.\n"); 977: printf("Usage: research < file.pgm >\n"); 978: exit(1); 979: } 980: else if(argc == 2) 981: strcpy(PGMfileName, argv[1]); 982: else 983: { 984: printf("To many parameters.\n"); 985: printf("Usage: research < file.pgm >\n"); 986: exit(1); 987: } 988: /* 989: * Read in image file. - note: sets our global values, too. 990: * ----------------------------------------------------------------- */ 991: 992: img0 = (PGMImage*) malloc(sizeof(PGMImage)); 993: getPGMfile(PGMfileName, img0); 994: HSIZE = (*img0).width; 995: VSIZE = (*img0).height; 996: MVAL = (*img0).maxVal; 997: 998: img_cur = img0; /*VERY IMPORTANT to set this*/ 999: 1000: /*allocate memory for second image*/ 1001: img1 = (PGMImage*) malloc(sizeof(PGMImage)); 1002: memcpy(img1, img0, sizeof(PGMImage)); 1003: /*(*img1).width = HSIZE; 1004: (*img1).height = VSIZE; 1005: (*img1).maxVal = 255;*/ 1006: 1007: img2 = (PGMImage*) malloc(sizeof(PGMImage)); 1008: memcpy(img2, img0, sizeof(PGMImage)); 1009: 1010: /* 1011: * Initialize the glut package. 1012: * ----------------------------------------------------------------- */ 1013: glutInit(&argc, argv); 1014: glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); 1015: /* 1016: * Define a new window (its size, position and title). 1017: * ----------------------------------------------------------------- */ 1018: glutInitWindowSize (HSIZE, VSIZE); /*size*/ 1019: glutInitWindowPosition (10, 10); /*position*/ 1020: WindowID = glutCreateWindow (PGMfileName); /*title*/ 1021: glutSetWindow(WindowID); 1022: glutDisplayFunc(color); 1023: 1024: /* 1025: * Call our init function to define viewing parameters. 1026: * ----------------------------------------------------------------- */ 1027: init (); 1028: 1029: glutMouseFunc(mouse); 1030: glutKeyboardFunc(keyboard); 1031: glutMainLoop(); 1032: 1033: /* 1034: * When we reach here, we've left the event loop and are ready to 1035: * exit. 1036: * ----------------------------------------------------------------- */ 1037: return 0; 1038: } 1039: 1040: 1041: 1042: 1043: 1044: 1045: 1046: 1047: 1048: 1049: 1050: 1051: