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