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 5
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:     printf("cur: (%d, %d)  check: (%d, %d)  dir: %d  ",
243:  	  x_current, y_current, x_check, y_check, *dir);
244:     printf("pxl_avg org: %d  pxl_chk org: %d\n",
245:  	  rgb_avg((*img).data[y_current][x_current]),
246:  	  rgb_avg((*img).data[y_check][x_check]));
247:        
248:     /*check for being in bounds*/
249:     if((x_check <  0) || (y_check <  0) || (x_check  >= (*img).width) ||
250:        (y_check  >= (*img).height))
251:        return FALSE;
252:  
253:     /*test condition for the end.*/
254:     else if(checkCode(*beginning, x_current, y_current, x_check, y_check,
255:  		     *dir) == NONE)
256:     {
257:        *dir = NONE;
258:        return FALSE;
259:     }
260:  
261:     /*tests if the next pixel is a boundry pixel.  If so does stuff*/
262:     if(pxlcmp((*img).data[y_current][x_current],
263:  	     (*img).data[y_check][x_check], 30))
264:     {
265:        setCPixel(x_check, y_check, chainColor);
266:        glFlush();
267:        *dir = next;
268:  printf("here\n");
269:        temp = (chain_t)malloc(sizeof(chainCode));
270:  printf("here2\n");
271:        temp- >next = NULL;
272:        temp- >code = *dir;
273:        temp- >location.x = x_check;
274:        temp- >location.y = y_check;
275:        temp- >prev = *theChain;
276:        if(*theChain)
277:           (*theChain)- >next = temp;  /*now this is a good thing to set.*/
278:        *theChain = temp;  /*advance one*/
279:  
280:        if(*beginning == NULL)
281:           *beginning = *theChain;/*set this for the first node in the list once*/       
282:        return TRUE;   
283:     }
284:     return FALSE;
285:  }  
286:  
287:  /*determines the chain code for a starting pixel*/
288:  /*this chain code uses 8 connectivity*/
289:  /*Note: There are many different coordinate systems at work in this function.*/
290:  /*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
291:  /*   top left is (0, 0).  If it looks strange, look harder!!!*/
292:  /*Preconditions:
293:  1st parameter: pointer to the pgm image being used.
294:  2nd parameter: integer value containing the current x coordinate.
295:  3rd parameter: integer value containing the current y coordinate.
296:  4th parameter: integer value containing the current direction code.
297:  5th parameter: pointer to the linked list of the chain code.
298:  6th parameter: pointer to the linked list of the chain code.*/
299:  /*This function assumes the (0, 0) point is in the lower left*/
300:           
301:  int chaincode(PGMImage *img, int x, int y, int dir, chainCode** theChain,
302:     chainCode** beginning)   
303:  {
304:     int i; /*loop counting*/
305:     int initial, next, finished;
306:      
307:     /*   if(dir % 2)   /*if dir is odd*/
308:     /* initial = (dir + 6) % 8;
309:     else          /*if dir is even*/
310:     /* initial = (dir + 7) % 8;*/
311:  
312:     initial = (dir + 5) % 8; /*better initail choice?*/
313:  
314:     next = initial; /*set the next direction to search*/
315:  printf("next: %d  x: %d  y: %d\n", next, x, y);   
316:     for(i = 0; i <  8; i++)
317:     {
318:        if(next == EAST)
319:        {
320:           if(checkThings(&dir, EAST, x, y, x + 1, y, theChain, img, beginning))
321:              finished = chaincode(img, x + 1, y, dir, theChain, beginning);
322:        }
323:        else if(next == NORTHEAST)
324:        {
325:           
326:           if(checkThings(&dir, NORTHEAST,  x, y, x + 1, y + 1, theChain, img,
327:              beginning))  
328:              finished = chaincode(img, x + 1, y + 1, dir, theChain, beginning);
329:        }
330:        else if(next == NORTH)   
331:        {  
332:           if(checkThings(&dir, NORTH,  x, y, x, y + 1, theChain, img,
333:              beginning))
334:              finished = chaincode(img, x, y + 1, dir, theChain, beginning);
335:        }
336:        else if(next == NORTHWEST)
337:        {
338:           if(checkThings(&dir, NORTHWEST,  x, y, x - 1, y + 1, theChain, img,
339:              beginning))  
340:              finished = chaincode(img, x - 1, y + 1, dir, theChain, beginning);
341:        }
342:        else if(next == WEST)
343:        {
344:           if(checkThings(&dir, WEST,  x, y, x - 1, y, theChain, img, beginning))
345:              finished = chaincode(img, x - 1, y, dir, theChain, beginning);
346:        }
347:        else if(next == SOUTHWEST)
348:        {  
349:           if(checkThings(&dir, SOUTHWEST,  x, y, x - 1, y - 1, theChain, img,
350:              beginning))  
351:              finished = chaincode(img, x - 1, y - 1, dir, theChain, beginning);
352:        }
353:        else if(next == SOUTH)   
354:        {  
355:           if(checkThings(&dir, SOUTH,  x, y, x, y - 1, theChain, img,beginning))
356:              finished = chaincode(img, x, y - 1, dir, theChain, beginning);
357:        }
358:        else if(next == SOUTHEAST)
359:        {
360:           if(checkThings(&dir, SOUTHEAST,  x, y, x + 1, y - 1, theChain, img,
361:              beginning))
362:              finished = chaincode(img, x + 1, y - 1, dir, theChain, beginning);
363:        }
364:         
365:        /*if the next chaincode function in the recursion or the current state
366:           is the final state of the the chain code; recursively returns DONE
367:           back through all the levels to stop the chain code.*/
368:        if(dir == NONE || finished == NONE)
369:           return NONE;
370:  
371:        /*set next for next iteration*/
372:        next = (next + 1) % 8;
373:     }
374:              
375:  }
376:  
377:  /*returns true if the point is already in one of the chains, false otherwise*/
378:  int alreadyFound(int initThreashFlag, int i, int j, PGMImage* img,
379:     chainCode** found, int count)
380:  {
381:     int k;
382:     chainCode* temp;
383:           /*this if statement determines if a pixel is not the background*/
384:           if(initThreashFlag <  rgb_avg((*img).data[j][i])) /*collumn major*/
385:           {
386:              /*Now search to determine if the pixel has been found already*/
387:              for(k = 0; k < = count; k++)
388:              {
389:                 temp = (found[k]);
390:                 while(temp)
391:                 {/* if point has already been found*/
392:                    if((temp- >location.x == i) && (temp- >location.y == j))
393:                    {
394:                       j = 0; /*does this work?*/
395:                       return TRUE;
396:                       break;
397:                    } 
398:                    temp = temp- >next;
399:                 }
400:              }
401:           }
402:     return FALSE;
403:  }
404:  
405:  /*saves a chain code to file.  Was usefull during debuging now is just
406:    a cool thing to leave in*/
407:  /*1st: pointer to beginning of a chaincode
408:  2nd: the index of the chain code for destiqushing the 'chain' files*/
409:  void saveChainCode(chainCode* saveChain, int count)
410:  {
411:     chainCode* temp = saveChain;
412:     char filename[12];
413:     FILE* outfile;
414:     sprintf(filename, "chain%d", count);
415:     outfile = fopen(filename, "w");   /*output file for chaincode*/
416:     printf("Writing chain code to file %s.\n", filename);
417:  
418:     while(temp)
419:     {
420:     
421:        fprintf(outfile, "%d  %d  %d\n",temp- >location.x,temp- >location.y,
422:           temp- >code);
423:        temp = temp- >next;
424:     }
425:     fclose(outfile);
426:  }
427:  
428:  chainCode** showChain(PGMImage *original)
429:  {
430:     int i, j;  /*loop counting*/
431:     int initThreashFlag = 128, foundFlag = TRUE;
432:     RGB_INT /*chainColor = {255, 0, 255},*/ tempColor = {255, 0, 0};
433:     chainCode** beginning, *chain = NULL, *temp, *next_tmep, *temp_loop;
434:     beginning = (chainCode**) malloc (MAX_CHAINS * sizeof(chainCode*));
435:     int count = 0; /*array index holder*/
436:     /*Need a temporary threasholded image*/
437:     /*PGMImage *threashed = (PGMImage*) malloc(sizeof(PGMImage));
438:      */               
439:     glPointSize(4); /*make points more visible*/
440:               
441:     /*showThreashold(original, threashed);*/
442:     
443:     /*Use starting pixel as defualt.  This is partially based on the fact that
444:     most likely a corner will be background and not an object.*/
445:     /*the image assumes that (0, 0) is in the bottom left, I assume that
446:       (0, 0) is in the upper left.  This is handled here.*/
447:     /*initThreashFlag = (*threashed).data[(*threashed).height - 1][0];*/
448:  
449:     for(i = 0; i <  10; i++) beginning[i] = NULL;/*initailize pointer array.*/  
450:     
451:     /*search image until a pixel is found with threasholded value of the
452:     object.  i & j will then contain the starting coordinate.*/
453:     for(i = 0; i <  (*original).width; i++) /*x direction*/
454:     {
455:        for(j = (*original).height - 1; j  >= 0; j--) /*y direction*/
456:        {
457:           /*skip to the next iteration if pixel isn't "good" enough*/
458:           if(rgb_avg((*original).data[j][i]) <  initThreashFlag)
459:           {
460:              continue;
461:           }        
462:           /*skip to the next iteration, which will be at the top of the next
463:             collumn*/
464:           else if(alreadyFound(initThreashFlag, i, j, original, beginning,
465:                  count))
466:           {
467:              j = 0; /*reseting to make this the last iteration without reseting
468:                         search to the top of next collumn*/
469:              continue;
470:           }
471:           else
472:           {
473:  /*printf("chaincode: %d\n", count);*/
474:             /*printf("The starting coordinate is (x, y): (%d, %d)\n", i, j);*/
475:              chain = NULL; /*reset this to seperate the chaincodes*/
476:  
477:  chainColor.blue = (128 + 10 * count) * (count % 2);
478:  chainColor.green =(128 + 10 * count) * (count % 3);
479:  chainColor.red =(128 + 10 * count);
480:              /*find the chaincode for the current starting pixel*/
481:              chaincode(original, i, j, SOUTHEAST, &chain, &beginning[count]);
482:  
483:  	    if(beginning[count] != NULL) /*avoid writing zero length chains*/
484:  	    {
485:  	       saveChainCode(beginning[count], count);
486:  	       count++; /*advance the beginning counter*/
487:  	    }
488:  
489:  	    /*force end of loops, leaving code when finished looping
490:  	      to still execute*/
491:  	    if(count  >= MAX_CHAINS)
492:  	       i = (*original).width;
493:  
494:              j = 0; /*reset search to start at top on next pass.  This the
495:                       setting for stopping condition for the current j loop.*/
496:              break; /*Quick fix?*/
497:           }
498:        }   
499:     }
500:     printf("Done finding chain code(s).  %d were found.\n", count);
501:     return beginning;
502:  }
503:  
504:  
505:  /**********************File I/O functions*******************************/
506:  /***********************************************************************/
507:  
508:  /*Gets an ascii color pgm image file (type P3).*/
509:  void getPGMfile (char filename[], PGMImage *img)
510:  {
511:    FILE *in_file;
512:    char ch;
513:    int row, col;
514:  
515:    in_file = fopen(filename, "r");
516:    if (in_file == NULL)
517:    {
518:      fprintf(stderr, "Error: Unable to open file %s\n\n", filename);
519:      exit(8);
520:    }
521:  
522:    printf("\nReading image file: %s", filename);
523:    
524:    do                                        /* skip header identifier */
525:      ch = getc(in_file);
526:    while (ch != '\n');
527:  
528:    do                                        /* skip comments lines    */
529:    {
530:      while (ch != '\n') ch = getc(in_file);  /*  flush to end of line  */
531:      ch = getc(in_file);
532:    } while (ch == '#');
533:   
534:    fseek(in_file, -1, SEEK_CUR);             /* backup one character   */
535:  
536:    fscanf(in_file,"%d", &((*img).width));
537:    fscanf(in_file,"%d", &((*img).height));
538:    fscanf(in_file,"%d", &((*img).maxVal));
539:  
540:    printf("\n width  = %d",(*img).width);
541:    printf("\n height = %d",(*img).height);
542:    printf("\n maxVal = %d",(*img).maxVal);
543:    printf("\n");
544:   
545:    if (((*img).width  > MAX) || ((*img).height  > MAX))
546:    {
547:      printf("\n\n***ERROR - image too big for current image structure***\n\n");
548:      exit(0);
549:    }
550:  
551:    for (row=(*img).height-1; row >=0; row--)
552:      for (col=0; col< (*img).width; col++)
553:      {
554:        fscanf(in_file,"%d", &((*img).data[row][col].red) );
555:        fscanf(in_file,"%d", &((*img).data[row][col].green));
556:        fscanf(in_file,"%d", &((*img).data[row][col].blue));
557:      }
558:    fclose(in_file);
559:    printf("\nDone reading file.\n");
560:  }
561:  
562:  
563:  void save(PGMImage *img)
564:  {
565:     int i, j, nr, nc, k;
566:     int red, green, blue;
567:     FILE *iop;
568:  
569:     nr = img- >height;
570:     nc = img- >width;
571:      
572:     iop = fopen("image1.pgm", "w");
573:     fprintf(iop, "P3\n");
574:     fprintf(iop, "%d %d\n", nc, nr);
575:     fprintf(iop, "255\n");
576:      
577:     k = 1;
578:     for(i = nr - 1; i  >= 0; i--)
579:     {
580:        for(j = 0; j <  nc; j++)
581:        {
582:           red = img- >data[i][j].red;
583:           green = img- >data[i][j].green;
584:           blue = img- >data[i][j].blue;
585:           if(red <  0)
586:           {
587:              printf("IMG_WRITE: Found value %d at row %d col %d\n", red, i, j);
588:              printf("           Setting red to zero\n");
589:              red = 0;
590:           }
591:           if(green <  0)   
592:           {
593:              printf("IMG_WRITE: Found value %d at row %d col %d\n", green,i, j);
594:              printf("           Setting green to zero\n");
595:              green = 0;
596:           }
597:           if(blue <  0)   
598:           {
599:              printf("IMG_WRITE: Found value %d at row %d col %d\n", blue, i, j);
600:              printf("           Setting green to zero\n");
601:              blue = 0;
602:           }
603:           if(red  > 255) 
604:           {   
605:              printf("IMG_WRITE: Found value %d at row %d col %d\n", red, i, j);
606:              printf("           Setting red to 255\n");
607:              red = 255;
608:           }
609:           if(green  > 255)
610:           {
611:              printf("IMG_WRITE: Found value %d at row %d col %d\n", green,i, j);
612:              printf("           Setting green to 255\n");
613:              green = 255;
614:           }
615:           if(blue  > 255)
616:           {
617:              printf("IMG_WRITE: Found value %d at row %d col %d\n", blue, i, j);
618:              printf("           Setting blue to 255\n");
619:              blue = 255;
620:           }
621:  
622:           if(k % 10)
623:           {
624:              fprintf(iop, "%d ", red);
625:              fprintf(iop, "%d ", green);
626:              fprintf(iop, "%d ", blue);
627:           }
628:           else /*for newline*/
629:           {
630:              fprintf(iop, "%d\n", red);
631:              fprintf(iop, "%d\n", green);
632:              fprintf(iop, "%d\n", blue);
633:           }
634:           k++;
635:        }
636:     }
637:     fprintf(iop, "\n");
638:     fclose(iop);
639:  }
640:  
641:  
642:  
643:  
644:  /****Calculation & drawing functions of the image translations**********
645:  ***********************************************************************/
646:              
647:            
648:  void showColor (PGMImage *img)
649:  {
650:     int row, col; /*y, x*/
651:     /*for (row=(*img).height-1; row >=0; row--)
652:        for (col=0; col< (*img).width; col++)
653:        {
654:  	 
655:  	 setCPixel(col, row, (*img).data[row][col]);
656:  	 }*/
657:  
658:     int i, j; /*loop counting: i = x, j = y*/
659:     int mid_width = ((*img).width / 2);
660:     int mid_height = ((*img).height / 2);
661:  
662:     for(i = 0; i <  mid_width / 2; i++)
663:     {
664:        for(j = 0; j <  mid_height; j++)
665:        {
666:  	/*inorder they are:
667:  	  bottom left, bottom middle right, top left, top m right,
668:  	  bottom middle left, bottom right, top middle left, top right.*/
669:  
670:  	 setCPixel(i, j, (*img).data[j][i]);
671:  	 setCPixel(i + mid_width, j, (*img).data[j][i + mid_width]);
672:  	 setCPixel(i, j + mid_height, (*img).data[j + mid_height][i]);
673:  	 setCPixel(i + mid_width, j + mid_height,
674:  		   (*img).data[j + mid_height][i + mid_width]);
675:  
676:  	 setCPixel(mid_width - i - 1, j,
677:  		   (*img).data[j][mid_width - i - 1]);
678:  	 setCPixel((*img).width - i - 1, j,
679:  		   (*img).data[j][(*img).width - i - 1]);
680:  	 setCPixel(mid_width - i - 1, (*img).height - j - 1,
681:  		   (*img).data[(*img).height - j - 1][mid_width - i - 1]);
682:  	 setCPixel((*img).width - i - 1, (*img).height - j - 1,
683:  		   (*img).data[(*img).height - j - 1][(*img).width - i - 1]);
684:        }
685:      }
686:      glFlush();
687:  }
688:  
689:  void camera_correction(PGMImage* new_img, PGMImage* org_img)
690:  {
691:     int row, col, img_row, img_col; /*loop counting*/
692:  
693:     /*camera parameters*/
694:     float height = 30; /*height of camera in cm*/
695:     float gamma = 0, theta = .698; /*camera angles = 40 degrees in rad*/
696:     float aperture = 1.1968, alpha = .598; /*aperature = 2 * alpha*/
697:     
698:     /*temporary varaibles*/
699:     float angular_height_corr;
700:     float angular_side_corr;
701:     int x_coord, y_coord;
702:  
703:     memset(new_img, 0, sizeof(PGMImage));
704:     (*new_img).height = (*org_img).height;
705:     (*new_img).width = (*org_img).width;
706:     (*new_img).maxVal = (*org_img).maxVal;
707:  
708:     for (row=(*org_img).height-1; row >=0; row--)
709:        for (col=0; col< (*org_img).width; col++)
710:        {
711:  	/*img_row -= (*org_img).height / 2;
712:  	  img_col = col - (*org_img).width / 2;*/
713:  
714:  	 angular_height_corr = 
715:     (theta - alpha) + col * (aperture / ((float)((*org_img).width) - 1));
716:  	 angular_side_corr =
717:     (gamma - alpha) + row * (aperture / ((float)((*org_img).height) - 1));
718:  
719:  	 angular_height_corr /= 2;
720:  	 /*angular_side_corr /= 2;*/
721:           /*height *= 2;*/
722:  	 height = 150;
723:  
724:  	 x_coord = (int)
725:  	   height * (1 / tan(angular_height_corr)) * cos(angular_side_corr);
726:  	 y_coord = (int)
727:  	   height * (1 / tan(angular_height_corr)) * sin(angular_side_corr);
728:  
729:  	 /*x_coord += (*org_img).width / 2;*/
730:  	 y_coord += (*org_img).height / 2;
731:  
732:  	 /*printf("org: (%d, %d)  new: (%d, %d)\n\n", row, col, y_coord, x_coord);*/
733:  
734:  	 pxlcpy(new_img, y_coord, x_coord, org_img, row, col);
735:        }
736:  }
737:  
738:  void new_corr(PGMImage* new_img, PGMImage* org_img)
739:  {
740:     /*i and j are the left half, k and l are the right half*/
741:     float i, k; /*loop counting*/
742:     int j, l, row; /*loop counting*/
743:     int old_i, old_k;
744:  
745:     float ins_s = 2; /*insert constant starting value*/
746:     float ins_k = ins_s; /*insert constant*/
747:  
748:     /*The halfway marks in the width.*/
749:     int mid_width_left = ((*new_img).width / 2) - 1;
750:     int mid_width_right = ((*new_img).width / 2);
751:     
752:     /*just to be thourough clear the memory and reset maxes*/
753:     memset(new_img, 0, sizeof(PGMImage));
754:     (*new_img).height = (*org_img).height;
755:     (*new_img).width = (*org_img).width;
756:     (*new_img).maxVal = (*org_img).maxVal;
757:  
758:     /*Loop through each row from top to bottom...*/
759:     for(row = ((*new_img).height - 1); row  >= 0; row--)
760:     {
761:        /*...reset moire interference removal counter...*/
762:        old_i = ((*new_img).width / 2) - 1;
763:        old_k = ((*new_img).width / 2);
764:  
765:        /*...so each half is ajusted to remove perspective effect...*/
766:        for(i = j = mid_width_left, k = l = mid_width_right
767:  	    ; i  >= 0, j  >= 0, k <  (*new_img).width, l <  (*new_img).width
768:  	    ; i -= ins_k, j--, k += ins_k, l++)
769:        {
770:  	 for(;old_i  >= (int)i; old_i--)  /*...in the left half...*/ 
771:  	    pxlcpy(new_img, row, old_i, org_img, row, j);
772:  	 for(;old_k < = (int)k; old_k++)  /*...in the right half.*/
773:  	    pxlcpy(new_img, row, old_k, org_img, row, l);
774:        }
775:        /*Move the new image x_coord pixel counter to next new image pixel*/
776:        ins_k -= ((ins_s - 1.0) / (*new_img).height);
777:     }
778:  }
779:  
780:  void color_to_gray(PGMImage* new_img, PGMImage* org_img)
781:  {
782:     int row, col; /*loop counting*/
783:     RGB_INT cur_pxl; /*current pixel*/
784:  
785:     (*new_img).height = (*org_img).height;
786:     (*new_img).width = (*org_img).width;
787:     (*new_img).maxVal = (*org_img).maxVal;
788:  
789:     /*Starting with the top row...*/
790:     for(row = (*new_img).height - 1; row  >= 0; row--)
791:        for(col = 0; col <  (*new_img).width - 1; col++)
792:        {
793:  	 cur_pxl = (*org_img).data[row][col]; /*more readable*/
794:  	
795:  	 /*convert each RGB to the average of the original*/
796:  	 (*new_img).data[row][col].red =  rgb_avg(cur_pxl);
797:  	 (*new_img).data[row][col].green =  rgb_avg(cur_pxl);
798:  	 (*new_img).data[row][col].blue =  rgb_avg(cur_pxl);
799:        }
800:  }
801:  
802:  void moravec(PGMImage* new_img, PGMImage* org_img)
803:  {
804:     int row, col; /*loop counting*/
805:     int i, j, k, l; /*Sanka, Hlavac & Boyle; p. 97 f. 4.73*/
806:     int running_sum;
807:     float K = .5; /*.125 according to org. formula, but .5 is brighter*/
808:     int max_val = 0, row_max, col_max; /* max porportion value in image*/
809:  
810:     memset(new_img, 0, sizeof(PGMImage));
811:     (*new_img).height = (*org_img).height;
812:     (*new_img).width = (*org_img).width;
813:     (*new_img).maxVal = (*org_img).maxVal;
814:  
815:     /*starting at the top row*/
816:     for(row = (*new_img).height - 1 - 1; row  > 0; row--)
817:        for(col = 1; col <  (*new_img).width - 1; col++) /*left col start*/
818:        {
819:  	 i = row;
820:  	 j = col;
821:  	 running_sum = 0;
822:  
823:  	 /*Sanka, Hlavac & Boyle; p. 97 f. 4.73*/
824:  	 for(k = i - 1; k < = i + 1; k++) /*row*/
825:  	   for(l = j - 1; l < = j + 1; l++) /*column*/
826:  	     running_sum += abs(rgb_avg((*org_img).data[k][l]) -
827:  				rgb_avg((*org_img).data[i][j]));
828:  
829:  	 /*assign the new pixel value*/
830:  	 (*new_img).data[row][col].red = (int)(K * running_sum);
831:  	 (*new_img).data[row][col].green = (int)(K * running_sum);
832:  	 (*new_img).data[row][col].blue = (int)(K * running_sum);
833:        } 
834:  }
835:  
836:  void detect_corners(PGMImage* org_img)
837:  {
838:     chainCode **chain_codes;
839:  
840:     chain_codes = showChain(org_img);
841:  }
842:  
843:  /* =================================================================
844:   * Callback functions.
845:   *
846:   * color = displayed graphics in window
847:   * menu = menu event handling
848:   * keyboard = deyboard event handling
849:   * ----------------------------------------------------------------- */
850:  void color(void)
851:  {
852:    /*glClear (GL_COLOR_BUFFER_BIT);*/
853:     
854:     /*  printf("\nDrawing Original image...\n");*/
855:    showColor(img_cur);
856:     
857:    /*glFlush();*/
858:  }
859:  
860:  #define RESTART 0
861:  #define CAMERA_CORRECTION 1
862:  #define X2_C_CORR 2
863:  #define NEW_CORR 3
864:  #define COLOR_TO_GRAY 4
865:  #define MORAVEC 5
866:  #define CORNERS 6
867:  
868:  void menu(int selection)
869:  {
870:     if(selection == RESTART)   
871:     {
872:        memcpy(img1, img0, sizeof(PGMImage));
873:        img_cur = img0;
874:     }
875:     if(selection == CAMERA_CORRECTION)
876:     {
877:        printf("Starting camera correction\n");
878:        camera_correction(img1, img0);
879:        img_cur = img1;
880:      }
881:      if(selection == X2_C_CORR)
882:      {
883:         printf("Starting camera correction\n");
884:         camera_correction(img1, img0);
885:         camera_correction(img2, img1);
886:         img_cur = img2;
887:      }
888:      if(selection == NEW_CORR)
889:      {
890:         new_corr(img1, img0);
891:         img_cur = img1;
892:      }
893:      if(selection == COLOR_TO_GRAY)
894:      {
895:         color_to_gray(img1, img0);
896:         img_cur = img1;
897:      }
898:      if(selection == MORAVEC)
899:      {
900:         moravec(img1, img0);
901:         img_cur = img1;
902:      }
903:      if(selection == CORNERS)
904:      {
905:        /*new_corr(img1, img0);*/
906:         /*moravec(img2, img1);*/
907:         showColor(img0);
908:         detect_corners(img0);
909:         img_cur = img0;
910:         return;
911:      }
912:      /*glClear (GL_COLOR_BUFFER_BIT);*/
913:      showColor(img_cur);
914:      glutPostRedisplay();
915:  }
916:  
917:  void keyboard(unsigned char key, int x, int y)
918:  { 
919:     switch (key)
920:     {
921:        case 27: 
922:           exit(0);
923:           break;
924:     }
925:  }
926:  
927:  void mouse(int button, int state, int x, int y)
928:  {
929:    char temp[50];
930:    RGB_INT erase = {0, 0, 0};
931:  
932:    if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
933:    {
934:       sprintf(temp, "(x, y): (%d, %d)  red: %d green: %d blue: %d\n",
935:  	     x, VSIZE - y, (*img_cur).data[VSIZE - y][x].red,
936:  	     (*img_cur).data[VSIZE - y][x].green,
937:  	     (*img_cur).data[VSIZE - y][x].blue);
938:       setCRect(0, 0, 200, 12, erase);
939:       glColor3f(1.0, 0.0, 0.0);
940:       drawString(0, 0, GLUT_BITMAP_TIMES_ROMAN_10, temp);
941:       glFlush();
942:    }
943:  }
944:    
945:  /* =================================================================
946:   * init - initializes graphics viewport
947:   *
948:   * You should not have to change this function for the first few
949:   * projects we have. It will become more important when we move to
950:   * 3D graphics.
951:   * ----------------------------------------------------------------- */
952:  void init (void)
953:  {
954:    
955:  /*
956:   * select clearing color - white
957:   */
958:     glClearColor (1.0, 1.0, 1.0, 0.0);
959:  
960:  /*
961:   * initialize viewport values
962:   */
963:     glMatrixMode(GL_PROJECTION);
964:     glLoadIdentity();
965:     glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
966:  
967:     /*add menus*/
968:     glutCreateMenu(menu);
969:     glutAddMenuEntry("Restart", RESTART);
970:     glutAddMenuEntry("Camera Correction", CAMERA_CORRECTION);
971:     glutAddMenuEntry("2x C. Corr.", X2_C_CORR);
972:     glutAddMenuEntry("new corr", NEW_CORR);
973:     glutAddMenuEntry("color to gray", COLOR_TO_GRAY);
974:     glutAddMenuEntry("moravec", MORAVEC);
975:     glutAddMenuEntry("corners", CORNERS);
976:     glutAttachMenu(GLUT_RIGHT_BUTTON);
977:  }
978:   
979:  int main(int argc, char** argv)
980:  {
981:     char PGMfileName[MAX_FILE_LENGTH];
982:     
983:     int WindowID;
984:  
985:     int i;  /*looping variable*/
986:      
987:     /*parse the command line*/  
988:     if(argc == 1)
989:     {
990:        printf("To few parameters.\n");
991:        printf("Usage: research < file.pgm >\n");
992:        exit(1);
993:     }
994:     else if(argc == 2)
995:        strcpy(PGMfileName, argv[1]);
996:     else
997:     {
998:        printf("To many parameters.\n");
999:        printf("Usage: research < file.pgm >\n");
1000:        exit(1);
1001:     }
1002:  /*
1003:   * Read in image file. - note: sets our global values, too.
1004:   * ----------------------------------------------------------------- */
1005:               
1006:     img0 = (PGMImage*) malloc(sizeof(PGMImage));
1007:     getPGMfile(PGMfileName, img0);
1008:     HSIZE = (*img0).width;
1009:     VSIZE = (*img0).height;
1010:     MVAL = (*img0).maxVal;
1011:  
1012:     img_cur = img0; /*VERY IMPORTANT to set this*/
1013:              
1014:     /*allocate memory for second image*/
1015:     img1 = (PGMImage*) malloc(sizeof(PGMImage));
1016:     memcpy(img1, img0, sizeof(PGMImage));
1017:     /*(*img1).width = HSIZE;
1018:     (*img1).height = VSIZE;
1019:     (*img1).maxVal = 255;*/
1020:               
1021:     img2 = (PGMImage*) malloc(sizeof(PGMImage));
1022:     memcpy(img2, img0, sizeof(PGMImage));
1023:              
1024:  /*
1025:   * Initialize the glut package.
1026:   * ----------------------------------------------------------------- */
1027:     glutInit(&argc, argv);
1028:     glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
1029:  /*           
1030:   * Define a new window (its size, position and title).
1031:   * ----------------------------------------------------------------- */
1032:        glutInitWindowSize (HSIZE, VSIZE);  /*size*/
1033:        glutInitWindowPosition (10, 10);    /*position*/
1034:        WindowID = glutCreateWindow (PGMfileName); /*title*/
1035:        glutSetWindow(WindowID);
1036:        glutDisplayFunc(color);
1037:        
1038:  /*  
1039:   * Call our init function to define viewing parameters.
1040:   * ----------------------------------------------------------------- */
1041:     init ();
1042:     
1043:     glutMouseFunc(mouse);
1044:     glutKeyboardFunc(keyboard); 
1045:     glutMainLoop();
1046:  
1047:  /*  
1048:   * When we reach here, we've left the event loop and are ready to
1049:   * exit.
1050:   * ----------------------------------------------------------------- */
1051:     return 0;
1052:  }
1053:  
1054:  
1055:  
1056:  
1057:  
1058:  
1059:  
1060:  
1061:  
1062:  
1063:  
1064:  
1065: