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:  /*cartesian coordinate type*/
18:  typedef struct {int x;
19:                  int y;}coord;  
20:  
21:  /*RGB color struct with floats*/ 
22:  /*typedef struct {float red;
23:                  float green;
24:                  float blue;
25:                 }RGB;
26:  */
27:  /*RGB color struct with ints*/  
28:  typedef struct {int red;
29:                  int green;
30:                  int blue;
31:                 }RGB_INT;
32:  
33:  /*number of chain codes stored, */  
34:  #define MAX_NUMBER_OF_CHAINS 10
35:  #define MAX_CHAINS MAX_NUMBER_OF_CHAINS
36:  
37:  /*These constant values are the chain code directions*/
38:  #define NONE      -1
39:  #define EAST      0
40:  #define NORTHEAST 1
41:  #define NORTH     2
42:  #define NORTHWEST 3
43:  #define WEST      4  
44:  #define SOUTHWEST 5
45:  #define SOUTH     6
46:  #define SOUTHEAST 7
47:  
48:  typedef struct chainCode* chain_t;
49:  typedef struct chainCode
50:  {
51:    chain_t prev;
52:    int code;    
53:    coord location; /*absolute pixel location for starting point*/
54:    chain_t next;
55:  }chainCode; /*This struct can be refered to by: struct chainCode or chainCode*/
56:  
57:  struct PGMstructure 
58:  {
59:    int maxVal;
60:    int width;
61:    int height;
62:    RGB_INT data[MAX][MAX];
63:  };
64:  
65:  typedef struct PGMstructure PGMImage;
66:  
67:  /*Evil globals, but not do-able otherwise.*/
68:  static PGMImage *img_cur;
69:  static PGMImage *img0; /*original*/
70:  static PGMImage *img1; /*current*/
71:  static PGMImage *img2; /*current*/
72:  static int HSIZE;
73:  static int VSIZE;
74:  static int MVAL;
75:  
76:  const RGB_INT color1 = {255, 255, 0};
77:  const RGB_INT color2 = {255, 0, 255};
78:  const RGB_INT color3 = {0, 255, 255};
79:  const RGB_INT color4 = {255, 0, 0};
80:  
81:  int cur_threash_val; /*for speed optimization of chain code recursion*/
82:  int cur_chain_count, back_ground;
83:  
84:  /**************Drawing funcitions************************************/
85:  /********************************************************************/
86:  
87:  void setCPixel(int ix, int iy, RGB_INT color)
88:  /*Same as setIPixel except that the last parameter is an RGB color*/
89:  {
90:    float x = (ix*2.0)/HSIZE - 1.0;
91:    float y = (iy*2.0)/VSIZE - 1.0;
92:  
93:    float red = (float)color.red/(float)MVAL;
94:    float green = (float)color.green/(float)MVAL;
95:    float blue = (float)color.blue/(float)MVAL;
96:  
97:    glColor3f(red, green, blue);
98:    
99:    glBegin(GL_POINTS); 
100:       glVertex2f (x, y);
101:    glEnd();
102:  }
103:  
104:  void setCLines(int ix1, int iy1, int ix2, int iy2, RGB_INT color)
105:  /*Similar as setIPixel except that this one draws a line between the first set
106:    of points given and the second set in the RGB color specified*/
107:  {
108:    float x1 = (ix1*2.0)/HSIZE - 1.0;
109:    float y1 = (iy1*2.0)/VSIZE - 1.0;
110:    float x2 = (ix2*2.0)/HSIZE - 1.0;
111:    float y2 = (iy2*2.0)/VSIZE - 1.0;
112:   
113:    float red = (float)color.red/(float)MVAL;
114:    float green = (float)color.green/(float)MVAL;
115:    float blue = (float)color.blue/(float)MVAL;
116:  
117:    glColor3f(red, green, blue);
118:  
119:    glBegin(GL_LINES);
120:      glVertex2f (x1, y1);
121:      glVertex2f (x2, y2);
122:    glEnd();
123:  }
124:  
125:  void setCRect(int ix1, int iy1, int ix2, int iy2, RGB_INT color)
126:  /*Similar as setIPixel except that this one draws a line between the first set
127:    of points given and the second set in the RGB color specified*/
128:  {
129:    float x1 = (ix1*2.0)/HSIZE - 1.0;
130:    float y1 = (iy1*2.0)/VSIZE - 1.0;
131:    float x2 = (ix2*2.0)/HSIZE - 1.0;
132:    float y2 = (iy2*2.0)/VSIZE - 1.0;
133:   
134:    float red = (float)color.red/(float)MVAL;
135:    float green = (float)color.green/(float)MVAL;
136:    float blue = (float)color.blue/(float)MVAL;
137:  
138:    glColor3f(red, green, blue);
139:  
140:    glBegin(GL_POLYGON);
141:      glVertex2f (x1, y1);
142:      glVertex2f (x1, y2);
143:      glVertex2f (x2, y2);
144:      glVertex2f (x2, y1);
145:    glEnd();
146:  }
147:  
148:  void pxlcpy(PGMImage *dest, int dest_row, int dest_col,
149:  	    PGMImage *src, int src_row, int src_col)
150:  {
151:    /*make sure values are within bounds*/
152:    if(dest_col > 0 && dest_col < (*dest).width
153:       && dest_row > 0 && dest_row < (*dest).height
154:       && src_col > 0 && src_col < (*src).width
155:       && src_row > 0 && src_row < (*src).height)
156:    {
157:      (*dest).data[dest_row][dest_col].red =
158:        (*src).data[src_row][src_col].red;
159:  
160:      (*dest).data[dest_row][dest_col].green =
161:        (*src).data[src_row][src_col].green;
162:  
163:      (*dest).data[dest_row][dest_col].blue =
164:        (*src).data[src_row][src_col].blue;
165:    }
166:  } 
167:  
168:  int rgb_avg(RGB_INT cur_pxl)
169:  {
170:     /*convert each RGB to the average of the original*/
171:     return ((cur_pxl.red + cur_pxl.green + cur_pxl.blue) / 3);
172:  }
173:  
174:  /*1st: pixel one of type RGB_INT
175:  2nd: pixel one of type RGB_INT
176:  3rd: differnce allowed to be considered "equal" or close enough*/
177:  int pxlcmp (RGB_INT pxl1, RGB_INT pxl2, int range)
178:  {
179:    return ((abs((rgb_avg(pxl1) - rgb_avg(pxl2)))) < range);
180:  }
181:  
182:  /* ================================================================= 
183:   * drawString - outputs a string of characters to the graphics port
184:   *
185:   *   x, y:      defines the starting location to draw the text
186:   *               note: this point is the lower left anchor of
187:   *                     the first character - a character's decending
188:   *                     portion would be drawn below this point.
189:   *   theFont:   points to the glut font to be used
190:   *   theString: holds the string to be output -- up to 255 ch
191:   * ----------------------------------------------------------------- */
192:  void drawString(int ix, int iy, void *theFont, char theString[256])
193:  {
194:     float x = (ix*2.0)/HSIZE - 1.0;
195:     float y = (iy*2.0)/VSIZE - 1.0;
196:     int i;
197:     glRasterPos2f(x, y);
198:     for (i = 0; theString[i] != '\0'; i++) /* draw the chars one at a time */
199:       glutBitmapCharacter(theFont, theString[i]);
200:  }
201:  
202:  /******CHAIN CODE************************************************
203:  ****************************************************************/
204:  
205:  int createNode(chainCode** first, chainCode** last, int new_x, int new_y,
206:  	       int new_dir)
207:  {
208:     chainCode* temp;
209:  
210:     if(!(temp = (chain_t)malloc(sizeof(struct chainCode))))
211:     {
212:       printf("error creating node\n");
213:        return FALSE;
214:     }
215:  
216:     temp->next = NULL;
217:     temp->code = new_dir;
218:     temp->location.x = new_x;
219:     temp->location.y = new_y;
220:     temp->prev = *last;
221:     if(*last)
222:       (*last)->next = temp;  /*now this is a good thing to set.*/
223:     *last = temp;  /*advance one*/
224:     
225:     if(*first == NULL)
226:       *first = *last;/*set this for the first node in the list once*/
227:  
228:     return TRUE;
229:  }
230:  
231:  /*returns TRUE if the chain code loops around itself, otherwise false*/
232:  int checkCode(chainCode* first, int x_current, int y_current,
233:  	      int x_check, int y_check, int dir)
234:  {
235:     struct chainCode* currentNode = first;
236:  
237:     while(currentNode && currentNode->next)
238:     {
239:        /*check two consedutive points*/
240:        if((currentNode->location.x == x_current) &&
241:           (currentNode->location.y == y_current) &&
242:           (currentNode->code == dir) &&
243:           (currentNode->next->location.x == x_check) &&
244:           (currentNode->next->location.y == y_check) &&
245:  	 (currentNode->next->next)) /*don't count the new node already*/
246:  	{
247:           return TRUE; /*The chain code end looped around*/
248:  	}
249:        else
250:           currentNode = currentNode->next;
251:     }
252:     
253:     return FALSE;
254:  
255:  }
256:  
257:  RGB_INT chainColor = {0, 0, 255};
258:  
259:  /*
260:  Preconditions:
261:  1st parameter: integer value containing the current x coordinate.
262:  2nd parameter: integer value containing the current y coordinate.
263:  3rd parameter: pointer to the pgm image being used.
264:  Postconditions:  return true if pixel is deemed boarder of object, false
265:     otherwise.*/
266:  int checkThings(int x_check, int y_check, PGMImage *img)
267:  {
268:  
269:     /*check for being in bounds*/
270:     if((x_check < 0) || (y_check < 0) || (x_check >= (*img).width) ||
271:        (y_check >= (*img).height))
272:        return FALSE;
273:  
274:     /*tests if the next pixel is greater than the threashing value.  This 
275:        value (cur_threash_val) should be set to the return value of 
276:        img_pxl_avg().  Also, checks if the pixel is considered in the background
277:        or forground agains the value in back_ground.  If so, return true to
278:        indicate create new node.*/
279:     if((rgb_avg((*img).data[y_check][x_check]) > cur_threash_val)
280:        && (back_ground < 0))
281:        return TRUE;   
282:  
283:     /*same thing as above, just for things less than, rathur than greater than*/
284:     if((rgb_avg((*img).data[y_check][x_check]) < cur_threash_val)
285:       && (back_ground > 0))
286:        return TRUE;
287:  
288:     return FALSE;
289:  }  
290:  
291:  coord neighborhood_point(int x_coord, int y_coord, int dir)
292:  {
293:     coord temp = {x_coord, y_coord};
294:  
295:     if(dir == EAST)
296:        temp.x++;
297:     else if(dir == NORTHEAST)
298:     {
299:        temp.x++;
300:        temp.y++;
301:     }
302:     else if(dir == NORTH)
303:        temp.y++;
304:     else if(dir == NORTHWEST)
305:     {
306:        temp.x--;
307:        temp.y++;
308:     }
309:     else if(dir == WEST)
310:        temp.x--;
311:     else if(dir == SOUTHWEST)
312:     {
313:        temp.x--;
314:        temp.y--;
315:     }
316:     else if(dir == SOUTH)
317:        temp.y--;
318:     else if(dir == SOUTHEAST)
319:     {
320:        temp.x++;
321:        temp.y--;
322:     }
323:  
324:     return temp;
325:  }
326:  
327:  /*determines the chain code for a starting pixel*/
328:  /*this chain code uses 8 connectivity*/
329:  /*Note: There are many different coordinate systems at work in this function.*/
330:  /*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
331:  /*   top left is (0, 0).  If it looks strange, look harder!!!*/
332:  /*Preconditions:
333:  1st parameter: pointer to the pgm image being used.
334:  2nd parameter: integer value containing the current x coordinate.
335:  3rd parameter: integer value containing the current y coordinate.
336:  4th parameter: integer value containing the current direction code.
337:  5th parameter: pointer to the last node of the chain code.
338:  6th parameter: pointer to the first node of the chain code.*/
339:  /*This function assumes the (0, 0) point is in the lower left*/
340:           
341:  int chaincode(PGMImage *img, int x, int y, int dir,
342:     struct chainCode** last, struct chainCode** first)   
343:  {
344:     int i; /*loop counting*/
345:     int next /*next direction to check*/, finished /*finished flag*/;
346:     coord next_point_to_check; /*next_point_to_check What else?*/
347:  
348:     next = (dir + 5) % 8; /*better initail choice?*/
349:  
350:  /*printf("next: %d  x: %d  y: %d\n", next, x, y);*/
351:     for(i = 0; i < 8; i++)
352:     {
353:        /*determine the next point to check*/
354:        next_point_to_check = neighborhood_point(x, y, next);
355:  
356:        if(checkThings(next_point_to_check.x, next_point_to_check.y, img))
357:        {
358:  	 setCPixel(next_point_to_check.x, next_point_to_check.y, chainColor);
359:  	 glFlush();
360:  	 /*create the new node to go last in the chain*/
361:  	 createNode(first, last, next_point_to_check.x,
362:  		    next_point_to_check.y, next);
363:  
364:  	 /*if the next chaincode function in the recursion or the current state
365:           is the final state of the the chain code; recursively returns DONE
366:           back through all the levels to stop the chain code.*/
367:  	 if(checkCode(*first, x, y, next_point_to_check.x,
368:  		    next_point_to_check.y, dir))
369:  	 {
370:  	    return NONE;
371:  	 }
372:  
373:  	 if(NONE == chaincode(img, next_point_to_check.x,
374:  			      next_point_to_check.y, next, last, first))
375:  	    return NONE;
376:        }
377:  
378:        /*set next for next iteration*/
379:        next = (next + 1) % 8;
380:     }
381:     return FALSE;         
382:  }
383:  
384:  /*returns true if the point is already in one of the chains, false otherwise*/
385:  int alreadyFound(int initThreashFlag, int i, int j, chainCode** found)
386:  {
387:     int k; /*loop counting*/
388:     chainCode* temp; /*temporary node pointer*/
389:  
390:     /*while there are codes to check...*/
391:     for(k = 0; (temp = (found[k])) && k < MAX_NUMBER_OF_CHAINS; k++)
392:     {
393:        while(temp) /*...check them.*/
394:        {
395:  	 /*if point has already been found*/
396:  	 if((temp->location.x == i) && (temp->location.y == j))
397:  	 {
398:  	    return TRUE;
399:  	    break;
400:  	 } 
401:  	 temp = temp->next;
402:        }
403:     }
404:     
405:     return FALSE;
406:  }
407:  
408:  /*saves a chain code to file.  Was usefull during debuging now is just
409:    a cool thing to leave in*/
410:  /*1st: pointer to beginning of a chaincode
411:  2nd: the index of the chain code for destiqushing the 'chain' files*/
412:  void saveChainCode(chainCode* saveChain, int count)
413:  {
414:     struct chainCode* temp = saveChain;
415:     char filename[12];
416:     FILE* outfile;
417:     sprintf(filename, "chain%d", count);
418:     outfile = fopen(filename, "w");   /*output file for chaincode*/
419:     printf("Writing chain code to file %s.\n", filename);
420:  
421:     while(temp)
422:     {
423:     
424:        fprintf(outfile, "%d  %d  %d\n",temp->location.x,temp->location.y,
425:           temp->code);
426:        temp = temp->next;
427:     }
428:     fclose(outfile);
429:  }
430:  
431:  chainCode** showChain(PGMImage *original)
432:  {
433:     int i, j;  /*loop counting*/
434:     int count = cur_chain_count = 0; /*array index holder*/
435:     int initThreashFlag = img_pxl_avg(original);
436:     /*beginning points to an array of pointers.  Each pointer in the array is
437:       a pointer to the first node of MAX_NUMBER_OF_CHAINS number of chain
438:       codes*/
439:     struct chainCode** beginning, *chain = NULL;
440:      
441:     /*allocate an array of pointers to chainCodes, then initalize their
442:       values to NULL*/
443:     beginning = (chainCode**)
444:       malloc(MAX_NUMBER_OF_CHAINS * sizeof(chainCode*));
445:     memset(beginning, 0, MAX_NUMBER_OF_CHAINS * sizeof(chainCode*));
446:     
447:     glPointSize(4); /*make points more visible, if desired*/
448:               
449:     cur_threash_val = initThreashFlag; /*set global variables*/
450:     back_ground = background(initThreashFlag, original);
451:  
452:     /*search image until a pixel is found with threasholded value of the
453:     object.  i & j will then contain the starting coordinate.*/
454:     for(i = 0; i < (*original).width; i++) /*x direction*/
455:     {
456:        for(j = (*original).height - 1; j >= 0; j--) /*y direction*/
457:        {
458:           /*skip to the next iteration if pixel isn't "good" enough*/
459:           if(!checkThings(i, j, original))
460:              continue;
461:  
462:           /*skip to the next iteration, which will be at the top of the next
463:             collumn.  This is true when the pixel has already been found in
464:  	   one of the chain codes.*/
465:           else if(alreadyFound(initThreashFlag, i, j, beginning))
466:  	    break;
467:  
468:           else
469:           {
470:  /*printf("chaincode: %d\n", count);*/
471:             /*printf("The starting coordinate is (x, y): (%d, %d)\n", i, j);*/
472:              chain = NULL; /*reset this to seperate the chaincodes*/
473:  
474:  	    /*color code the chaincodes in the global RGB_INT*/
475:  	    chainColor.blue = (128 + 10 * count) * (count % 2);
476:  	    chainColor.green =(128 + 10 * count) * (count % 3);
477:  	    chainColor.red =(128 + 10 * count);
478:  
479:              /*find the chaincode for the current starting pixel*/
480:              chaincode(original, i, j, SOUTHEAST, &chain, &beginning[count]);
481:  	    if(beginning[count] != NULL) /*avoid writing zero length chains*/
482:  	    {
483:  	       saveChainCode(beginning[count], count);
484:  	       count++; /*advance the beginning counter*/
485:                 cur_chain_count = count;
486:  	    }
487:  
488:  	    /*force end of loops, leaving code when finished looping
489:  	      to still execute*/
490:  	    if(count >= MAX_NUMBER_OF_CHAINS)
491:  	       i = (*original).width;
492:  
493:              /*j = 0;*/ /*reset search to start at top on next pass.  This the
494:                       setting for stopping condition for the current j loop.*/
495:              break; /*Quick fix?*/
496:           }
497:        }   
498:     }
499:     printf("Done finding chain code(s).  %d were found.\n", count);
500:     return beginning;
501:  }
502:  
503:  /*****BOUNDRY BOX**********************************************************
504:   **********************************************************************/
505:     
506:  /*takes two coordinates as x and y pairs and returns the distence betweem them
507:     as a decimal*/
508:  float findDist(int x1, int y1, int x2, int y2)
509:  {
510:    //return sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2));
511:     return sqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)));
512:  }
513:           
514:  /*takes two coordinate as x and y pairs and returns the slope of the line
515:    between them*/
516:  float findSlope(int x1, int y1, int x2, int y2)
517:  {
518:     return (float)(y1 - y2) / (float)(x1 - x2);
519:  }
520:  
521:  /*1st param: The array of coords that the first point of the major axis is
522:     returned in.
523:  2nd: The array of coords that the second point of the major axis is
524:     returned in.
525:  3rd: The array of chain codes that are searched through to find the major
526:     axes.*/
527:  /* Note: the ending condition is when a NULL chainCodes value is reached.
528:     Thusly, it works like a string requiring it to have the last legal value
529:     followed by a null value.*/
530:  void findMajor(coord max1[], coord max2[], chainCode** chainCodes)
531:  {
532:     int i = 0; /*loop counting*/
533:     chainCode *temp = NULL, *search;
534:     double max_dist = 0.0, test_dist;
535:  
536:     printf("\nFinding major.\n");
537:  
538:     /*as long as there are codes to check, keep checking.  Note: the ending
539:     condition is when a NULL chainCodes value is reached.  Thusly, it works
540:     like a string requiring it to have the last legal value followed by a
541:     null value.*/
542:     while(temp = chainCodes[i]) /*look at each objects seperatly*/
543:     {      
544:        max_dist = 0.0;  /*reset this for each iteration*/
545:  /*printf("checking list: %d\n", i);*/
546:        while(temp)
547:        {
548:           search = temp; /*set the faster moving temp pointer to the first,
549:                            this increases the effiecency a lot.*/
550:           while(search)
551:           {
552:  setCPixel(temp->location.x, temp->location.y, color4);
553:              /*determine if found a new maximum distance between two locations*/
554:              if((test_dist = findDist(search->location.x, search->location.y,
555:                 temp->location.x, temp->location.y)) > max_dist)
556:              {
557:                 max_dist = test_dist;
558:                 max1[i].x = temp->location.x;
559:                 max1[i].y = temp->location.y;
560:                 max2[i].x = search->location.x;
561:                 max2[i].y = search->location.y;
562:              }
563:              search = search->next;
564:           }
565:           temp = temp->next;
566:        }
567:     
568:  /*printf("point1: %d  %d\n", max1[i].x, max1[i].y);
569:  printf("point2: %d  %d\n", max2[i].x, max2[i].y);*/
570:         
571:     
572:        i++; /*advance to the next list*/
573:     }
574:  }
575:  
576:  /*1st param: The array of coords that the first point of the minor axis is
577:     returned in.
578:  2nd: The array of coords that the second point of the minor axis is
579:     returned in.
580:  3rd: The array of chain codes that are searched through to find the minor
581:     axes.*/
582:  /*Note: the ending condition is when a NULL chainCodes value is reached.
583:     Thusly, it works like a string requiring it to have the last legal value
584:     followed by a null value.*/
585:  void findMinor(coord min1[], coord min2[], coord max1[], coord max2[],
586:     chainCode** chainCodes)
587:  {
588:     int i = 0; /*loop counting*/
589:     chainCode *temp = NULL, *search;
590:     double min_dist = 0.0, test_dist;
591:     float slope, minor_slope;
592:         
593:     printf("\nFinding minor.\n");
594:        
595:     /*as long as there are codes to check, keep checking.  Note: the ending
596:     condition is when a NULL chainCodes value is reached.  Thusly, it works
597:     like a string requiring it to have the last legal value followed by a
598:     null value.*/
599:     while(temp = chainCodes[i]) /*look at each object seperatly*/
600:     {
601:  //printf("checking list: %d\n", i);
602:        min_dist = 0.0;  /*reset this for each iteration*/
603:        /*find slope 90 degrees from major axis*/
604:        slope = -1 / findSlope(max1[i].x, max1[i].y, max2[i].x, max2[i].y);
605:  //printf("point1: %d %d   point2: %d, %d\n", max1[i].x, max1[i].y, max2[i].x,
606:  //   max2[i].y);
607:  //printf("Using slope: %f\n", slope);
608:        min1[i].x = -1;  /*set default values in case of no minor axis*/
609:        min1[i].y = -1;
610:        min2[i].x = -1;
611:        min2[i].y = -1;
612:     
613:        while(temp)
614:        {
615:           search = temp;/*set the faster moving temp pointer to the first,
616:                            this increases the effiecency a lot.*/
617:           while(search)
618:           {
619:  setCPixel(temp->location.x, temp->location.y, color3);
620:  
621:              /*determine if found a new maximum distance between two locations,
622:                 and it is 90 degrees to the major axis*/
623:              test_dist = findDist(temp->location.x, temp->location.y,
624:                 search->location.x, search->location.y);
625:        
626:              /*when there isn't a division by zero, find the minor slope*/
627:              if(temp->location.x - search->location.x)
628:                 minor_slope = findSlope(temp->location.x, temp->location.y,   
629:                    search->location.x, search->location.y);
630:              else /*if there is division by zero, next iteration*/
631:              {
632:                 search = search->next;
633:                 continue;
634:              }
635:              /*if they are the fartheset points so far and are perpendicular
636:                do the slope of the major axis (to withing .01 error).*/
637:              if((test_dist > min_dist) && (.01 > fabs(minor_slope - slope)))
638:              {
639:                 min_dist = test_dist;
640:                 min1[i].x = temp->location.x;
641:                 min1[i].y = temp->location.y;
642:                 min2[i].x = search->location.x;
643:                 min2[i].y = search->location.y;
644:              }
645:              search = search->next;
646:           }
647:           temp = temp->next;
648:        }
649:              
650:  /*printf("point1: %d  %d\n", min1[i].x, min1[i].y);  
651:  printf("point2: %d  %d\n", min2[i].x, min2[i].y);*/
652:                    
653:        i++; /*advance to the next list*/
654:     }
655:  }
656:  
657:  /*calculate the bounding box corners from the major and minor axes*/
658:  /*1st param: The first array of minor axes coords.
659:  2nd: The second array of minor axes coords.
660:  3rd: The first array of major axes coords.
661:  4th: The second array of major axes coords.
662:  5th: The array of coords the first bounding box corner is returned in.
663:  6th: The array of coords the second bounding box corner is returned in.
664:  7th: The array of coords the third bounding box corner is returned in.
665:  8th: The array of coords the fourth bounding box corner is returned in.
666:  9th: And integer containing the number of objects that was found.  This
667:     speeds up the execution by avoiding looking at objects that aren't there.*/
668:  void findBound(coord min1[], coord min2[], coord max1[], coord max2[],
669:     coord corner1[], coord corner2[], coord corner3[], coord corner4[],
670:     int count)
671:  {           
672:     int i;
673:     float major_slope, minor_slope;
674:                    
675:     printf("\nFinding Boundry Box.\n"); 
676:      
677:     for(i = 0; i < count; i++) /*look at each object seperatly*/
678:     {           
679:        if((min1[i].x == -1) && (min2[i].x == -1) && (min1[i].y == -1) &&
680:         (min2[i].y == -1))
681:        {
682:          /*printf("Unable to find bound for the list %d.\n", i + 1);*/
683:           corner1[i].x = corner2[i].x = corner3[i].x = corner4[i].x = -1;
684:           corner1[i].y = corner2[i].y = corner3[i].y = corner4[i].y = -1;
685:           continue;
686:        }
687:  
688:        /*find the major slope*/
689:        major_slope = findSlope(max1[i].x, max1[i].y, max2[i].x, max2[i].y);
690:     
691:        /*find the minor slope*/
692:        minor_slope = findSlope(min1[i].x, min1[i].y, min2[i].x,  min2[i].y);
693:     
694:        /*find first point*/
695:        /*use max1 and min1 for the corner calcuations*/
696:        corner1[i].x = Round((float)
697:           ((minor_slope * max1[i].x) - (major_slope * min1[i].x)
698:           - max1[i].y + min1[i].y) / (float)(minor_slope - major_slope));
699:        corner1[i].y =
700:           Round(minor_slope * (corner1[i].x - max1[i].x) + max1[i].y);
701:                 
702:        
703:        /*find second point*/
704:        /*use max2 and min2 for the corner calculations*/
705:        corner2[i].x = Round((float)
706:           ((minor_slope * max2[i].x) - (major_slope * min2[i].x)
707:           - max2[i].y + min2[i].y) / (float)(minor_slope - major_slope));
708:        corner2[i].y =
709:           Round(minor_slope * (corner2[i].x - max2[i].x) + max2[i].y);
710:  
711:        /*find third point*/
712:        /*use max1 and min2 for the corner calcuations*/
713:        corner3[i].x = Round((float)
714:           ((minor_slope * max1[i].x) - (major_slope * min2[i].x)
715:           - max1[i].y + min2[i].y) / (float)(minor_slope - major_slope));   
716:        corner3[i].y =
717:           Round(minor_slope * (corner3[i].x - max1[i].x) + max1[i].y);
718:        
719:        /*find second point*/
720:        /*use max2 and min1 for the corner calcuations*/
721:        corner4[i].x = Round((float)
722:           ((minor_slope * max2[i].x) - (major_slope * min1[i].x)
723:           - max2[i].y + min1[i].y) / (float)(minor_slope - major_slope));
724:        corner4[i].y =
725:           Round(minor_slope * (corner4[i].x - max2[i].x) + max2[i].y);
726:        
727:  /*printf("corner1: %d  %d\n", corner1[i].x, corner1[i].y);*/
728:  /*printf("corner2: %d  %d\n", corner2[i].x, corner2[i].y);*/
729:  /*printf("corner3: %d  %d\n", corner3[i].x, corner3[i].y);*/   
730:  /*printf("corner4: %d  %d\n", corner4[i].x, corner4[i].y);*/
731:     }
732:  }
733:  
734:  /*takes the chaincode array as paramter and counts up how many objects
735:    are stored in the array of chaincodes.  The result is an integer that is
736:    returned.*/
737:  int countChains(chainCode** toCount)
738:  {
739:     chainCode** temp = toCount;
740:     int i = 0;
741:     for(i = 0; temp[i]; i++) ; /*count the number of chainCodes*/
742:     return i;
743:  }
744:  
745:  /*Finds the center of each object from the major and minor axes intersections*/
746:  /*1st:  The first array of minor axis coords.
747:  2nd:  The second array of minro axis coords.
748:  3rd: The first array of major axis coords.
749:  4th: The second array of major axis coords.
750:  5th: The array of coords that the center coords are returned in.
751:  6th: The number of chaincodes that have valid values in the previous
752:     array parameters passed in.*/
753:  void findCenter(coord min1[], coord min2[], coord max1[], coord max2[],
754:     coord center[], int count)
755:  {
756:     int i;
757:     float major_slope, minor_slope;
758:  
759:     printf("\nFinding Center.\n");
760:    
761:     for(i = 0; i < count; i++)
762:     {
763:        /*if a minor axis wasn't found, skip to the next*/
764:        /*also skip if there is no slope*/
765:        if((min1[i].x == -1 && min1[i].y == -1 && min2[i].x == -1 &&
766:        min2[i].y == -1) || (max1[i].y == max2[i].y) || (min1[i].y == min2[i].y))
767:        {
768:          /*printf("Unable to find center for list %d.\n", i);*/
769:           center[i].x = center[i].y = -1;
770:           continue;
771:        }
772:  
773:        major_slope = findSlope(max1[i].x, max1[i].y, max2[i].x, max2[i].y);
774:        minor_slope = findSlope(min1[i].x, min1[i].y, min2[i].x, min2[i].y);
775:  
776:        center[i].x = Round((float)(
777:       -major_slope * max1[i].x + minor_slope * min1[i].x + max1[i].y - min1[i].y
778:         ) / (float)(-major_slope + minor_slope));
779:     
780:        center[i].y = Round(major_slope * (float)(center[i].x - max1[i].x) +
781:           (float)max1[i].y);
782:     }
783:  } 
784:  
785:  /*takes an pointer to an image, and a pointer pointing to an array of
786:    chain codes pointers, here each chainCode pointer needs to be accessed
787:    by calculating the memory address.*/
788:  void showBound(PGMImage *original, chainCode** chainCodes)
789:  {     
790:     int numberOfChains;
791:     int i;
792:     /*hold the points farthest away from each other for each object*/
793:     coord max1[MAX_CHAINS], max2[MAX_CHAINS];
794:     coord min1[MAX_CHAINS], min2[MAX_CHAINS];
795:     coord corner1[MAX_CHAINS], corner2[MAX_CHAINS];
796:     coord corner3[MAX_CHAINS], corner4[MAX_CHAINS];
797:     coord center[MAX_CHAINS];
798:  
799:     numberOfChains = countChains(chainCodes);
800:  
801:     findMajor(max1, max2, chainCodes);
802:     findMinor(min1, min2, max1, max2, chainCodes);
803:     findBound(min1, min2, max1, max2, corner1, corner2, corner3, corner4,
804:  	     numberOfChains);
805:     findCenter(min1, min2, max1, max2, center, numberOfChains);
806:        
807:     for(i = 0; i < numberOfChains; i++)  
808:     {
809:        /*draw the major axes*/
810:        setCPixel(max1[i].x, max1[i].y, color1);
811:        setCPixel(max2[i].x, max2[i].y, color1);
812:        setCLines(max1[i].x, max1[i].y, max2[i].x, max2[i].y, color2);
813:           
814:        /*draw the minor axes*/
815:        setCPixel(min1[i].x, min1[i].y, color1);
816:        setCPixel(min2[i].x, min2[i].y, color1);
817:        setCLines(min1[i].x, min1[i].y, min2[i].x, min2[i].y, color2);
818:  
819:        /*draw the boundry box*/
820:        setCPixel(corner1[i].x, corner1[i].y, color1);
821:        setCPixel(corner2[i].x, corner2[i].y, color1);
822:        setCPixel(corner3[i].x, corner3[i].y, color1);
823:        setCPixel(corner4[i].x, corner4[i].y, color1);
824:        setCLines(corner1[i].x, corner1[i].y, corner3[i].x, corner3[i].y,color3);
825:        setCLines(corner4[i].x, corner4[i].y, corner2[i].x, corner2[i].y,color3);
826:        setCLines(corner3[i].x, corner3[i].y, corner2[i].x, corner2[i].y,color3);
827:        setCLines(corner4[i].x, corner4[i].y, corner1[i].x, corner1[i].y,color3);
828:     
829:        /*draw the centroid pixel*/
830:        setCPixel(center[i].x, center[i].y, color4);
831:     }
832:  }
833:  
834:  
835:  /**********************Support functions*******************************/
836:  /***********************************************************************/
837:  
838:  /*Returns average (with RGB avg) pixel value for the image passed in.*/
839:  int img_pxl_avg(PGMImage* img)
840:  {
841:     int i, j; /*loop counting*/
842:     int sum = 0;
843:  
844:     for(i = 0; i < (*img).height; i++)/*collumn*/
845:        for(j = 0; j < (*img).width; j++)/*row*/
846:           sum += rgb_avg((*img).data[i][j]);
847:  
848:     return (sum / ((*img).height * (*img).height));
849:  }
850:  
851:  /*return >0 if number of pixels is greater than img. pxl. avg., return <0 if
852:    number of pixesl is less than img. pxl. avg. and return zero of equal*/
853:  int background(int treash_value, PGMImage* img)
854:  {
855:     int i, j; /*loop counting*/
856:     int pxl_less = 0, pxl_more = 0;
857:  
858:     for(i = 0; i < (*img).height; i++)/*collumn*/
859:        for(j = 0; j < (*img).width; j++)/*row*/
860:        {
861:  	 if(rgb_avg((*img).data[i][j]) < treash_value)
862:  	   pxl_less++;
863:  
864:           if(rgb_avg((*img).data[i][j]) > treash_value)
865:  	   pxl_more++;
866:        }
867:  
868:     printf("lesser: %d  greater: %d\n", pxl_less, pxl_more);
869:  
870:     if(pxl_less > pxl_more)
871:        return -1;
872:     else if(pxl_less < pxl_more)
873:        return 1;
874:     else
875:        return 0;
876:  }
877:  
878:  /**********************File I/O functions*******************************/
879:  /***********************************************************************/
880:  
881:  /*Gets an ascii color pgm image file (type P3).*/
882:  void getPGMfile (char filename[], PGMImage *img)
883:  {
884:    FILE *in_file;
885:    char ch;
886:    int row, col;
887:  
888:    in_file = fopen(filename, "r");
889:    if (in_file == NULL)
890:    {
891:      fprintf(stderr, "Error: Unable to open file %s\n\n", filename);
892:      exit(8);
893:    }
894:  
895:    printf("\nReading image file: %s", filename);
896:    
897:    do                                        /* skip header identifier */
898:      ch = getc(in_file);
899:    while (ch != '\n');
900:  
901:    do                                        /* skip comments lines    */
902:    {
903:      while (ch != '\n') ch = getc(in_file);  /*  flush to end of line  */
904:      ch = getc(in_file);
905:    } while (ch == '#');
906:   
907:    fseek(in_file, -1, SEEK_CUR);             /* backup one character   */
908:  
909:    fscanf(in_file,"%d", &((*img).width));
910:    fscanf(in_file,"%d", &((*img).height));
911:    fscanf(in_file,"%d", &((*img).maxVal));
912:  
913:    printf("\n width  = %d",(*img).width);
914:    printf("\n height = %d",(*img).height);
915:    printf("\n maxVal = %d",(*img).maxVal);
916:    printf("\n");
917:   
918:    if (((*img).width > MAX) || ((*img).height > MAX))
919:    {
920:      printf("\n\n***ERROR - image too big for current image structure***\n\n");
921:      exit(0);
922:    }
923:  
924:    for (row=(*img).height-1; row>=0; row--)
925:      for (col=0; col<(*img).width; col++)
926:      {
927:        fscanf(in_file,"%d", &((*img).data[row][col].red) );
928:        fscanf(in_file,"%d", &((*img).data[row][col].green));
929:        fscanf(in_file,"%d", &((*img).data[row][col].blue));
930:      }
931:    fclose(in_file);
932:    printf("\nDone reading file.\n");
933:  }
934:  
935:  
936:  void save(PGMImage *img)
937:  {
938:     int i, j, nr, nc, k;
939:     int red, green, blue;
940:     FILE *iop;
941:  
942:     nr = img->height;
943:     nc = img->width;
944:      
945:     iop = fopen("image1.pgm", "w");
946:     fprintf(iop, "P3\n");
947:     fprintf(iop, "%d %d\n", nc, nr);
948:     fprintf(iop, "255\n");
949:      
950:     k = 1;
951:     for(i = nr - 1; i >= 0; i--)
952:     {
953:        for(j = 0; j < nc; j++)
954:        {
955:           red = img->data[i][j].red;
956:           green = img->data[i][j].green;
957:           blue = img->data[i][j].blue;
958:           if(red < 0)
959:           {
960:              printf("IMG_WRITE: Found value %d at row %d col %d\n", red, i, j);
961:              printf("           Setting red to zero\n");
962:              red = 0;
963:           }
964:           if(green < 0)   
965:           {
966:              printf("IMG_WRITE: Found value %d at row %d col %d\n", green,i, j);
967:              printf("           Setting green to zero\n");
968:              green = 0;
969:           }
970:           if(blue < 0)   
971:           {
972:              printf("IMG_WRITE: Found value %d at row %d col %d\n", blue, i, j);
973:              printf("           Setting green to zero\n");
974:              blue = 0;
975:           }
976:           if(red > 255) 
977:           {   
978:              printf("IMG_WRITE: Found value %d at row %d col %d\n", red, i, j);
979:              printf("           Setting red to 255\n");
980:              red = 255;
981:           }
982:           if(green > 255)
983:           {
984:              printf("IMG_WRITE: Found value %d at row %d col %d\n", green,i, j);
985:              printf("           Setting green to 255\n");
986:              green = 255;
987:           }
988:           if(blue > 255)
989:           {
990:              printf("IMG_WRITE: Found value %d at row %d col %d\n", blue, i, j);
991:              printf("           Setting blue to 255\n");
992:              blue = 255;
993:           }
994:  
995:           if(k % 10)
996:           {
997:              fprintf(iop, "%d ", red);
998:              fprintf(iop, "%d ", green);
999:              fprintf(iop, "%d ", blue);
1000:           }
1001:           else /*for newline*/
1002:           {
1003:              fprintf(iop, "%d\n", red);
1004:              fprintf(iop, "%d\n", green);
1005:              fprintf(iop, "%d\n", blue);
1006:           }
1007:           k++;
1008:        }
1009:     }
1010:     fprintf(iop, "\n");
1011:     fclose(iop);
1012:  }
1013:  
1014:  
1015:  
1016:  
1017:  /****Calculation & drawing functions of the image translations**********
1018:  ***********************************************************************/
1019:              
1020:            
1021:  void showColor (PGMImage *img)
1022:  {
1023:     int row, col; /*y, x*/
1024:     /*for (row=(*img).height-1; row>=0; row--)
1025:        for (col=0; col<(*img).width; col++)
1026:        {
1027:  	 
1028:  	 setCPixel(col, row, (*img).data[row][col]);
1029:  	 }*/
1030:  
1031:     int i, j; /*loop counting: i = x, j = y*/
1032:     int mid_width = ((*img).width / 2);
1033:     int mid_height = ((*img).height / 2);
1034:  
1035:     for(i = 0; i < mid_width / 2; i++)
1036:     {
1037:        for(j = 0; j < mid_height; j++)
1038:        {
1039:  	/*inorder they are:
1040:  	  bottom left, bottom middle right, top left, top m right,
1041:  	  bottom middle left, bottom right, top middle left, top right.*/
1042:  
1043:  	 setCPixel(i, j, (*img).data[j][i]);
1044:  	 setCPixel(i + mid_width, j, (*img).data[j][i + mid_width]);
1045:  	 setCPixel(i, j + mid_height, (*img).data[j + mid_height][i]);
1046:  	 setCPixel(i + mid_width, j + mid_height,
1047:  		   (*img).data[j + mid_height][i + mid_width]);
1048:  
1049:  	 setCPixel(mid_width - i - 1, j,
1050:  		   (*img).data[j][mid_width - i - 1]);
1051:  	 setCPixel((*img).width - i - 1, j,
1052:  		   (*img).data[j][(*img).width - i - 1]);
1053:  	 setCPixel(mid_width - i - 1, (*img).height - j - 1,
1054:  		   (*img).data[(*img).height - j - 1][mid_width - i - 1]);
1055:  	 setCPixel((*img).width - i - 1, (*img).height - j - 1,
1056:  		   (*img).data[(*img).height - j - 1][(*img).width - i - 1]);
1057:        }
1058:      }
1059:      glFlush();
1060:  }
1061:  
1062:  void camera_correction(PGMImage* new_img, PGMImage* org_img)
1063:  {
1064:     int row, col, img_row, img_col; /*loop counting*/
1065:  
1066:     /*camera parameters*/
1067:     float height = 30; /*height of camera in cm*/
1068:     float gamma = 0, theta = .698; /*camera angles = 40 degrees in rad*/
1069:     float aperture = 1.1968, alpha = .598; /*aperature = 2 * alpha*/
1070:     
1071:     /*temporary varaibles*/
1072:     float angular_height_corr;
1073:     float angular_side_corr;
1074:     int x_coord, y_coord;
1075:  
1076:     memset(new_img, 0, sizeof(PGMImage));
1077:     (*new_img).height = (*org_img).height;
1078:     (*new_img).width = (*org_img).width;
1079:     (*new_img).maxVal = (*org_img).maxVal;
1080:  
1081:     for (row=(*org_img).height-1; row>=0; row--)
1082:        for (col=0; col<(*org_img).width; col++)
1083:        {
1084:  	/*img_row -= (*org_img).height / 2;
1085:  	  img_col = col - (*org_img).width / 2;*/
1086:  
1087:  	 angular_height_corr = 
1088:     (theta - alpha) + col * (aperture / ((float)((*org_img).width) - 1));
1089:  	 angular_side_corr =
1090:     (gamma - alpha) + row * (aperture / ((float)((*org_img).height) - 1));
1091:  
1092:  	 angular_height_corr /= 2;
1093:  	 /*angular_side_corr /= 2;*/
1094:           /*height *= 2;*/
1095:  	 height = 150;
1096:  
1097:  	 x_coord = (int)
1098:  	   (height * (1 / tan(angular_height_corr)) * cos(angular_side_corr));
1099:  	 y_coord = (int)
1100:  	   (height * (1 / tan(angular_height_corr)) * sin(angular_side_corr));
1101:  
1102:  	 /*x_coord += (*org_img).width / 2;*/
1103:  	 y_coord += (*org_img).height / 2;
1104:  
1105:  	 /*printf("org: (%d, %d)  new: (%d, %d)\n\n", row, col, y_coord, x_coord);*/
1106:  
1107:  	 pxlcpy(new_img, y_coord, x_coord, org_img, row, col);
1108:        }
1109:  }
1110:  
1111:  void new_corr(PGMImage* new_img, PGMImage* org_img)
1112:  {
1113:     /*i and j are the left half, k and l are the right half*/
1114:     float i, k; /*loop counting*/
1115:     int j, l, row; /*loop counting*/
1116:     int old_i, old_k;
1117:  
1118:     float ins_s = 2; /*insert constant starting value*/
1119:     float ins_k = ins_s; /*insert constant*/
1120:  
1121:     /*The halfway marks in the width.*/
1122:     int mid_width_left = ((*new_img).width / 2) - 1;
1123:     int mid_width_right = ((*new_img).width / 2);
1124:     
1125:     /*just to be thourough clear the memory and reset maxes*/
1126:     memset(new_img, 0, sizeof(PGMImage));
1127:     (*new_img).height = (*org_img).height;
1128:     (*new_img).width = (*org_img).width;
1129:     (*new_img).maxVal = (*org_img).maxVal;
1130:  
1131:     /*Loop through each row from top to bottom...*/
1132:     for(row = ((*new_img).height - 1); row >= 0; row--)
1133:     {
1134:        /*...reset moire interference removal counter...*/
1135:        old_i = ((*new_img).width / 2) - 1;
1136:        old_k = ((*new_img).width / 2);
1137:  
1138:        /*...so each half is ajusted to remove perspective effect...*/
1139:        for(i = j = mid_width_left, k = l = mid_width_right
1140:  	    ; i >= 0, j >= 0, k < (*new_img).width, l < (*new_img).width
1141:  	    ; i -= ins_k, j--, k += ins_k, l++)
1142:        {
1143:  	 for(;old_i >= (int)i; old_i--)  /*...in the left half...*/ 
1144:  	    pxlcpy(new_img, row, old_i, org_img, row, j);
1145:  	 for(;old_k <= (int)k; old_k++)  /*...in the right half.*/
1146:  	    pxlcpy(new_img, row, old_k, org_img, row, l);
1147:        }
1148:        /*Move the new image x_coord pixel counter to next new image pixel*/
1149:        ins_k -= ((ins_s - 1.0) / (*new_img).height);
1150:     }
1151:  }
1152:  
1153:  void color_to_gray(PGMImage* new_img, PGMImage* org_img)
1154:  {
1155:     int row, col; /*loop counting*/
1156:     RGB_INT cur_pxl; /*current pixel*/
1157:  
1158:     (*new_img).height = (*org_img).height;
1159:     (*new_img).width = (*org_img).width;
1160:     (*new_img).maxVal = (*org_img).maxVal;
1161:  
1162:     /*Starting with the top row...*/
1163:     for(row = (*new_img).height - 1; row >= 0; row--)
1164:        for(col = 0; col < (*new_img).width - 1; col++)
1165:        {
1166:  	 cur_pxl = (*org_img).data[row][col]; /*more readable*/
1167:  	
1168:  	 /*convert each RGB to the average of the original*/
1169:  	 (*new_img).data[row][col].red =  rgb_avg(cur_pxl);
1170:  	 (*new_img).data[row][col].green =  rgb_avg(cur_pxl);
1171:  	 (*new_img).data[row][col].blue =  rgb_avg(cur_pxl);
1172:        }
1173:  }
1174:  
1175:  void moravec(PGMImage* new_img, PGMImage* org_img)
1176:  {
1177:     int row, col; /*loop counting*/
1178:     int i, j, k, l; /*Sanka, Hlavac & Boyle; p. 97 f. 4.73*/
1179:     int running_sum;
1180:     float K = .5; /*.125 according to org. formula, but .5 is brighter*/
1181:     int max_val = 0, row_max, col_max; /* max porportion value in image*/
1182:  
1183:     memset(new_img, 0, sizeof(PGMImage));
1184:     (*new_img).height = (*org_img).height;
1185:     (*new_img).width = (*org_img).width;
1186:     (*new_img).maxVal = (*org_img).maxVal;
1187:  
1188:     /*starting at the top row*/
1189:     for(row = (*new_img).height - 1 - 1; row > 0; row--)
1190:        for(col = 1; col < (*new_img).width - 1; col++) /*left col start*/
1191:        {
1192:  	 i = row;
1193:  	 j = col;
1194:  	 running_sum = 0;
1195:  
1196:  	 /*Sanka, Hlavac & Boyle; p. 97 f. 4.73*/
1197:  	 for(k = i - 1; k <= i + 1; k++) /*row*/
1198:  	   for(l = j - 1; l <= j + 1; l++) /*column*/
1199:  	     running_sum += abs(rgb_avg((*org_img).data[k][l]) -
1200:  				rgb_avg((*org_img).data[i][j]));
1201:  
1202:  	 /*assign the new pixel value*/
1203:  	 (*new_img).data[row][col].red = (int)(K * running_sum);
1204:  	 (*new_img).data[row][col].green = (int)(K * running_sum);
1205:  	 (*new_img).data[row][col].blue = (int)(K * running_sum);
1206:        } 
1207:  }
1208:  
1209:  void detect_corners(PGMImage* org_img)
1210:  {
1211:     /*pointer to an array of pointers which point to the first nodes in each of
1212:       the chain codes.*/ 
1213:     chainCode **chain_codes;
1214:  
1215:     chain_codes = showChain(org_img);
1216:     showBound(org_img, chain_codes);
1217:  
1218:     glFlush();/*force drawing*/
1219:  }
1220:  
1221:  /* =================================================================
1222:   * Callback functions.
1223:   *
1224:   * color = displayed graphics in window
1225:   * menu = menu event handling
1226:   * keyboard = deyboard event handling
1227:   * ----------------------------------------------------------------- */
1228:  void color(void)
1229:  {
1230:    /*glClear (GL_COLOR_BUFFER_BIT);*/
1231:     
1232:     /*  printf("\nDrawing Original image...\n");*/
1233:    showColor(img_cur);
1234:     
1235:    /*glFlush();*/
1236:  }
1237:  
1238:  #define RESTART 0
1239:  #define CAMERA_CORRECTION 1
1240:  #define X2_C_CORR 2
1241:  #define NEW_CORR 3
1242:  #define COLOR_TO_GRAY 4
1243:  #define MORAVEC 5
1244:  #define CORNERS 6
1245:  
1246:  void menu(int selection)
1247:  {
1248:     if(selection == RESTART)   
1249:     {
1250:        memcpy(img1, img0, sizeof(PGMImage));
1251:        img_cur = img0;
1252:     }
1253:     if(selection == CAMERA_CORRECTION)
1254:     {
1255:        printf("Starting camera correction\n");
1256:        camera_correction(img1, img0);
1257:        img_cur = img1;
1258:      }
1259:      if(selection == X2_C_CORR)
1260:      {
1261:         printf("Starting camera correction\n");
1262:         camera_correction(img1, img0);
1263:         camera_correction(img2, img1);
1264:         img_cur = img2;
1265:      }
1266:      if(selection == NEW_CORR)
1267:      {
1268:         new_corr(img1, img0);
1269:         img_cur = img1;
1270:      }
1271:      if(selection == COLOR_TO_GRAY)
1272:      {
1273:         color_to_gray(img1, img0);
1274:         img_cur = img1;
1275:      }
1276:      if(selection == MORAVEC)
1277:      {
1278:         moravec(img1, img0);
1279:         img_cur = img1;
1280:      }
1281:      if(selection == CORNERS)
1282:      {
1283:  printf("img avg: %d\n", img_pxl_avg(img0));
1284:        new_corr(img1, img0);
1285:         /*moravec(img2, img1);*/
1286:        showColor(img1);
1287:         detect_corners(img1);
1288:         img_cur = img1;
1289:         return;
1290:      }
1291:      /*glClear (GL_COLOR_BUFFER_BIT);*/
1292:      showColor(img_cur);
1293:      glutPostRedisplay();
1294:  }
1295:  
1296:  void keyboard(unsigned char key, int x, int y)
1297:  { 
1298:     switch (key)
1299:     {
1300:        case 27: 
1301:           exit(0);
1302:           break;
1303:     }
1304:  }
1305:  
1306:  void mouse(int button, int state, int x, int y)
1307:  {
1308:    char temp[50];
1309:    RGB_INT erase = {0, 0, 0};
1310:  
1311:    if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
1312:    {
1313:       sprintf(temp, "(x, y): (%d, %d)  red: %d green: %d blue: %d\n",
1314:  	     x, VSIZE - y, (*img_cur).data[VSIZE - y][x].red,
1315:  	     (*img_cur).data[VSIZE - y][x].green,
1316:  	     (*img_cur).data[VSIZE - y][x].blue);
1317:       setCRect(0, 0, 200, 12, erase);
1318:       glColor3f(1.0, 0.0, 0.0);
1319:       drawString(0, 0, GLUT_BITMAP_TIMES_ROMAN_10, temp);
1320:       glFlush();
1321:    }
1322:  }
1323:    
1324:  /* =================================================================
1325:   * init - initializes graphics viewport
1326:   *
1327:   * You should not have to change this function for the first few
1328:   * projects we have. It will become more important when we move to
1329:   * 3D graphics.
1330:   * ----------------------------------------------------------------- */
1331:  void init (void)
1332:  {
1333:    
1334:  /*
1335:   * select clearing color - white
1336:   */
1337:     glClearColor (1.0, 1.0, 1.0, 0.0);
1338:  
1339:  /*
1340:   * initialize viewport values
1341:   */
1342:     glMatrixMode(GL_PROJECTION);
1343:     glLoadIdentity();
1344:     glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
1345:  
1346:     /*add menus*/
1347:     glutCreateMenu(menu);
1348:     glutAddMenuEntry("Restart", RESTART);
1349:     glutAddMenuEntry("Camera Correction", CAMERA_CORRECTION);
1350:     glutAddMenuEntry("2x C. Corr.", X2_C_CORR);
1351:     glutAddMenuEntry("new corr", NEW_CORR);
1352:     glutAddMenuEntry("color to gray", COLOR_TO_GRAY);
1353:     glutAddMenuEntry("moravec", MORAVEC);
1354:     glutAddMenuEntry("corners", CORNERS);
1355:     glutAttachMenu(GLUT_RIGHT_BUTTON);
1356:  }
1357:   
1358:  int main(int argc, char** argv)
1359:  {
1360:     char PGMfileName[MAX_FILE_LENGTH];
1361:     
1362:     int WindowID;
1363:  
1364:     int i;  /*looping variable*/
1365:      
1366:     /*parse the command line*/  
1367:     if(argc == 1)
1368:     {
1369:        printf("To few parameters.\n");
1370:        printf("Usage: research <file.pgm>\n");
1371:        exit(1);
1372:     }
1373:     else if(argc == 2)
1374:        strcpy(PGMfileName, argv[1]);
1375:     else
1376:     {
1377:        printf("To many parameters.\n");
1378:        printf("Usage: research <file.pgm>\n");
1379:        exit(1);
1380:     }
1381:  /*
1382:   * Read in image file. - note: sets our global values, too.
1383:   * ----------------------------------------------------------------- */
1384:               
1385:     img0 = (PGMImage*) malloc(sizeof(PGMImage));
1386:     getPGMfile(PGMfileName, img0);
1387:     HSIZE = (*img0).width;
1388:     VSIZE = (*img0).height;
1389:     MVAL = (*img0).maxVal;
1390:  
1391:     img_cur = img0; /*VERY IMPORTANT to set this*/
1392:              
1393:     /*allocate memory for second image*/
1394:     img1 = (PGMImage*) malloc(sizeof(PGMImage));
1395:     memcpy(img1, img0, sizeof(PGMImage));
1396:     /*(*img1).width = HSIZE;
1397:     (*img1).height = VSIZE;
1398:     (*img1).maxVal = 255;*/
1399:               
1400:     img2 = (PGMImage*) malloc(sizeof(PGMImage));
1401:     memcpy(img2, img0, sizeof(PGMImage));
1402:              
1403:  /*
1404:   * Initialize the glut package.
1405:   * ----------------------------------------------------------------- */
1406:     glutInit(&argc, argv);
1407:     glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
1408:  /*           
1409:   * Define a new window (its size, position and title).
1410:   * ----------------------------------------------------------------- */
1411:        glutInitWindowSize (HSIZE, VSIZE);  /*size*/
1412:        glutInitWindowPosition (10, 10);    /*position*/
1413:        WindowID = glutCreateWindow (PGMfileName); /*title*/
1414:        glutSetWindow(WindowID);
1415:        glutDisplayFunc(color);
1416:        
1417:  /*  
1418:   * Call our init function to define viewing parameters.
1419:   * ----------------------------------------------------------------- */
1420:     init ();
1421:     
1422:     glutMouseFunc(mouse);
1423:     glutKeyboardFunc(keyboard); 
1424:     glutMainLoop();
1425:  
1426:  /*  
1427:   * When we reach here, we've left the event loop and are ready to
1428:   * exit.
1429:   * ----------------------------------------------------------------- */
1430:     return 0;
1431:  }
1432:  
1433:  
1434:  
1435:  
1436:  
1437:  
1438:  
1439:  
1440:  
1441:  
1442:  
1443:  
1444: