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: