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