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