1:  #include < GL/glut.h >
2:  #include < stdlib.h >
3:  #include < stdio.h >
4:  #include < string.h >
5:  #include < math.h >
6:  #include < iostream.h >
7:  
8:  #define Round(v) ((int)(v+0.5))
9:  #define MAX 800
10:  #define MAX_FILE_LENGTH 256
11:    
12:  #define LOW_VALUE 0 
13:  #define HIGH_VALUE 255
14:  
15:  #define TRUE 1
16:  #define FALSE 0  
17:  
18:  /*cartesian coordinate type*/
19:  typedef struct {int x;
20:                  int y;}coord;  
21:  
22:  /*RGB color struct*/ 
23:  typedef struct {float red;
24:                  float green;
25:                  float blue;
26:                 }RGB;
27:  
28:  /*RGB color struct*/  
29:  typedef struct {int red;
30:                  int green;
31:                  int blue;
32:                 }RGB_INT;
33:  
34:  struct PGMstructure 
35:  {
36:    int maxVal;
37:    int width;
38:    int height;
39:    RGB_INT data[MAX][MAX];
40:  };
41:  
42:  typedef struct PGMstructure PGMImage;
43:  
44:  /*Evil globals, but not do-able otherwise.*/
45:  static PGMImage *img_cur;
46:  static PGMImage *img0; /*original*/
47:  static PGMImage *img1; /*current*/
48:  static PGMImage *img2; /*current*/
49:  static int HSIZE;
50:  static int VSIZE;
51:  static int MVAL;
52:  
53:  /**************Drawing funcitions************************************/
54:  /********************************************************************/
55:  
56:  void setCPixel(int ix, int iy, RGB_INT color)
57:  /*Same as setIPixel except that the last parameter is an RGB color*/
58:  {
59:    RGB pixel_color;
60:    float x = (ix*2.0)/HSIZE - 1.0;
61:    float y = (iy*2.0)/VSIZE - 1.0;
62:  
63:    pixel_color.red = (float)color.red/(float)MVAL;
64:    pixel_color.green = (float)color.green/(float)MVAL;
65:    pixel_color.blue = (float)color.blue/(float)MVAL;
66:  
67:    glColor3f(pixel_color.red, pixel_color.green, pixel_color.blue);
68:    
69:    glBegin(GL_POINTS); 
70:       glVertex2f (x, y);
71:    glEnd();
72:  }
73:  
74:  void pxlcpy(PGMImage *dest, int dest_row, int dest_col,
75:  	    PGMImage *src, int src_row, int src_col)
76:  {
77:    /*make sure values are within bounds*/
78:    if(dest_col  > 0 && dest_col <  (*dest).width
79:       && dest_row  > 0 && dest_row <  (*dest).height
80:  && src_col  > 0 && src_col <  (*src).width
81:       && src_row  > 0 && src_row <  (*src).height)
82:    {
83:      (*dest).data[dest_row][dest_col].red =
84:        (*src).data[src_row][src_col].red;
85:  
86:      (*dest).data[dest_row][dest_col].green =
87:        (*src).data[src_row][src_col].green;
88:  
89:      (*dest).data[dest_row][dest_col].blue =
90:        (*src).data[src_row][src_col].blue;
91:    }
92:  } 
93:  
94:  
95:  /**********************File I/O functions*******************************/
96:  /***********************************************************************/
97:  
98:  /*Gets an ascii color pgm image file (type P3).*/
99:  void getPGMfile (char filename[], PGMImage *img)
100:  {
101:    FILE *in_file;
102:    char ch;
103:    int row, col;
104:  
105:    in_file = fopen(filename, "r");
106:    if (in_file == NULL)
107:    {
108:      fprintf(stderr, "Error: Unable to open file %s\n\n", filename);
109:      exit(8);
110:    }
111:  
112:    printf("\nReading image file: %s", filename);
113:    
114:    do                                        /* skip header identifier */
115:      ch = getc(in_file);
116:    while (ch != '\n');
117:  
118:    do                                        /* skip comments lines    */
119:    {
120:      while (ch != '\n') ch = getc(in_file);  /*  flush to end of line  */
121:      ch = getc(in_file);
122:    } while (ch == '#');
123:   
124:    fseek(in_file, -1, SEEK_CUR);             /* backup one character   */
125:  
126:    fscanf(in_file,"%d", &((*img).width));
127:    fscanf(in_file,"%d", &((*img).height));
128:    fscanf(in_file,"%d", &((*img).maxVal));
129:  
130:    printf("\n width  = %d",(*img).width);
131:    printf("\n height = %d",(*img).height);
132:    printf("\n maxVal = %d",(*img).maxVal);
133:    printf("\n");
134:   
135:    if (((*img).width  > MAX) || ((*img).height  > MAX))
136:    {
137:      printf("\n\n***ERROR - image too big for current image structure***\n\n");
138:      exit(0);
139:    }
140:  
141:    for (row=(*img).height-1; row >=0; row--)
142:      for (col=0; col< (*img).width; col++)
143:      {
144:        fscanf(in_file,"%d", &((*img).data[row][col].red) );
145:        fscanf(in_file,"%d", &((*img).data[row][col].green));
146:        fscanf(in_file,"%d", &((*img).data[row][col].blue));
147:      }
148:    fclose(in_file);
149:    printf("\nDone reading file.\n");
150:  }
151:  
152:  
153:  void save(PGMImage *img)
154:  {
155:     int i, j, nr, nc, k;
156:     int red, green, blue;
157:     FILE *iop;
158:  
159:     nr = img- >height;
160:     nc = img- >width;
161:      
162:     iop = fopen("image1.pgm", "w");
163:     fprintf(iop, "P3\n");
164:     fprintf(iop, "%d %d\n", nc, nr);
165:     fprintf(iop, "255\n");
166:      
167:     k = 1;
168:     for(i = nr - 1; i  >= 0; i--)
169:     {
170:        for(j = 0; j <  nc; j++)
171:        {
172:           red = img- >data[i][j].red;
173:           green = img- >data[i][j].green;
174:           blue = img- >data[i][j].blue;
175:           if(red <  0)
176:           {
177:              printf("IMG_WRITE: Found value %d at row %d col %d\n", red, i, j);
178:              printf("           Setting red to zero\n");
179:              red = 0;
180:           }
181:           if(green <  0)   
182:           {
183:              printf("IMG_WRITE: Found value %d at row %d col %d\n", green,i, j);
184:              printf("           Setting green to zero\n");
185:              green = 0;
186:           }
187:           if(blue <  0)   
188:           {
189:              printf("IMG_WRITE: Found value %d at row %d col %d\n", blue, i, j);
190:              printf("           Setting green to zero\n");
191:              blue = 0;
192:           }
193:           if(red  > 255) 
194:           {   
195:              printf("IMG_WRITE: Found value %d at row %d col %d\n", red, i, j);
196:              printf("           Setting red to 255\n");
197:              red = 255;
198:           }
199:           if(green  > 255)
200:           {
201:              printf("IMG_WRITE: Found value %d at row %d col %d\n", green,i, j);
202:              printf("           Setting green to 255\n");
203:              green = 255;
204:           }
205:           if(blue  > 255)
206:           {
207:              printf("IMG_WRITE: Found value %d at row %d col %d\n", blue, i, j);
208:              printf("           Setting blue to 255\n");
209:              blue = 255;
210:           }
211:  
212:           if(k % 10)
213:           {
214:              fprintf(iop, "%d ", red);
215:              fprintf(iop, "%d ", green);
216:              fprintf(iop, "%d ", blue);
217:           }
218:           else /*for newline*/
219:           {
220:              fprintf(iop, "%d\n", red);
221:              fprintf(iop, "%d\n", green);
222:              fprintf(iop, "%d\n", blue);
223:           }
224:           k++;
225:        }
226:     }
227:     fprintf(iop, "\n");
228:     fclose(iop);
229:  }
230:  
231:  
232:  /****Calculation & drawing functions of the image translations**********
233:  ***********************************************************************/
234:              
235:            
236:  void showColor (PGMImage *img)
237:  {
238:     int row, col; /*y, x*/
239:     /*for (row=(*img).height-1; row >=0; row--)
240:        for (col=0; col< (*img).width; col++)
241:        {
242:  	 
243:  	 setCPixel(col, row, (*img).data[row][col]);
244:  	 }*/
245:  
246:     int i, j; /*loop counting: i = x, j = y*/
247:     int mid_width = ((*img).width / 2);
248:     int mid_height = ((*img).height / 2);
249:  
250:     for(i = 0; i <  mid_width / 2; i++)
251:     {
252:        for(j = 0; j <  mid_height; j++)
253:        {
254:  	/*inorder they are:
255:  	  bottom left, bottom middle right, top left, top m right,
256:  	  bottom middle left, bottom right, top middle left, top right.*/
257:  
258:  	 setCPixel(i, j, (*img).data[j][i]);
259:  	 setCPixel(i + mid_width, j, (*img).data[j][i + mid_width]);
260:  	 setCPixel(i, j + mid_height, (*img).data[j + mid_height][i]);
261:  	 setCPixel(i + mid_width, j + mid_height,
262:  		   (*img).data[j + mid_height][i + mid_width]);
263:  
264:  	 setCPixel(mid_width - i - 1, j,
265:  		   (*img).data[j][mid_width - i - 1]);
266:  	 setCPixel((*img).width - i - 1, j,
267:  		   (*img).data[j][(*img).width - i - 1]);
268:  	 setCPixel(mid_width - i - 1, (*img).height - j - 1,
269:  		   (*img).data[(*img).height - j - 1][mid_width - i - 1]);
270:  	 setCPixel((*img).width - i - 1, (*img).height - j - 1,
271:  		   (*img).data[(*img).height - j - 1][(*img).width - i - 1]);
272:        }
273:      }
274:  
275:     glFlush ();
276:  }
277:  
278:  void camera_correction(PGMImage* new_img, PGMImage* org_img)
279:  {
280:     int row, col, img_row, img_col; /*loop counting*/
281:  
282:     /*camera parameters*/
283:     float height = 30; /*height of camera in cm*/
284:     float gamma = 0, theta = .698; /*camera angles = 40 degrees in rad*/
285:     float aperture = 1.1968, alpha = .598; /*aperature = 2 * alpha*/
286:     
287:     /*temporary varaibles*/
288:     float angular_height_corr;
289:     float angular_side_corr;
290:     int x_coord, y_coord;
291:  
292:     memset(new_img, 0, sizeof(PGMImage));
293:     (*new_img).height = (*org_img).height;
294:     (*new_img).width = (*org_img).width;
295:     (*new_img).maxVal = (*org_img).maxVal;
296:  
297:     for (row=(*org_img).height-1; row >=0; row--)
298:        for (col=0; col< (*org_img).width; col++)
299:        {
300:  	/*img_row -= (*org_img).height / 2;
301:  	  img_col = col - (*org_img).width / 2;*/
302:  
303:  	 angular_height_corr = 
304:     (theta - alpha) + col * (aperture / ((float)((*org_img).width) - 1));
305:  	 angular_side_corr =
306:     (gamma - alpha) + row * (aperture / ((float)((*org_img).height) - 1));
307:  
308:  	 angular_height_corr /= 2;
309:  	 /*angular_side_corr /= 2;*/
310:           /*height *= 2;*/
311:  	 height = 150;
312:  
313:  	 x_coord = (int)
314:  	   height * (1 / tan(angular_height_corr)) * cos(angular_side_corr);
315:  	 y_coord = (int)
316:  	   height * (1 / tan(angular_height_corr)) * sin(angular_side_corr);
317:  
318:  	 /*x_coord += (*org_img).width / 2;*/
319:  	 y_coord += (*org_img).height / 2;
320:  
321:  	 /*printf("org: (%d, %d)  new: (%d, %d)\n\n", row, col, y_coord, x_coord);*/
322:  
323:  	 pxlcpy(new_img, y_coord, x_coord, org_img, row, col);
324:        }
325:  }
326:  
327:  void new_corr(PGMImage* new_img, PGMImage* org_img)
328:  {
329:     /*i and j are the left half, k and l are the right half*/
330:     float i, k; /*loop counting*/
331:     int j, l, row; /*loop counting*/
332:     int old_i, old_k;
333:  
334:     float ins_s = 2; /*insert constant starting value*/
335:     float ins_k = ins_s; /*insert constant*/
336:  
337:     /*The halfway marks in the width.*/
338:     int mid_width_left = ((*new_img).width / 2) - 1;
339:     int mid_width_right = ((*new_img).width / 2);
340:     
341:     /*just to be thourough clear the memory and reset maxes*/
342:     memset(new_img, 0, sizeof(PGMImage));
343:     (*new_img).height = (*org_img).height;
344:     (*new_img).width = (*org_img).width;
345:     (*new_img).maxVal = (*org_img).maxVal;
346:  
347:     /*Loop through each row from top to bottom...*/
348:     for(row = ((*new_img).height - 1); row  >= 0; row--)
349:     {
350:        /*...reset moire interference removal counter...*/
351:        old_i = ((*new_img).width / 2) - 1;
352:        old_k = ((*new_img).width / 2);
353:  
354:        /*...so each half is ajusted to remove perspective effect...*/
355:        for(i = j = mid_width_left, k = l = mid_width_right
356:  	    ; i  >= 0, j  >= 0, k <  (*new_img).width, l <  (*new_img).width
357:  	    ; i -= ins_k, j--, k += ins_k, l++)
358:        {
359:  	 for(;old_i  >= (int)i; old_i--)  /*...in the left half...*/ 
360:  	    pxlcpy(new_img, row, old_i, org_img, row, j);
361:  	 for(;old_k < = (int)k; old_k++)  /*...in the right half.*/
362:  	    pxlcpy(new_img, row, old_k, org_img, row, l);
363:        }
364:        /*Move the new image x_coord pixel counter to next new image pixel*/
365:        ins_k -= ((ins_s - 1.0) / (*new_img).height);
366:     }
367:  }
368:  
369:  void color_to_gray(PGMImage* new_img, PGMImage* org_img)
370:  {
371:     int row, col; /*loop counting*/
372:     RGB_INT cur_pxl; /*current pixel*/
373:  
374:     (*new_img).height = (*org_img).height;
375:     (*new_img).width = (*org_img).width;
376:     (*new_img).maxVal = (*org_img).maxVal;
377:  
378:     /*Starting with the top row...*/
379:     for(row = (*new_img).height - 1; row  >= 0; row--)
380:        for(col = 0; col <  (*new_img).width - 1; col++)
381:        {
382:  	 cur_pxl = (*org_img).data[row][col]; /*more readable*/
383:  	
384:  	 /*convert each RGB to the average of the original*/
385:           (*new_img).data[row][col].red =
386:  	   (cur_pxl.red + cur_pxl.green + cur_pxl.blue) / 3;
387:  	 (*new_img).data[row][col].green =
388:  	   (cur_pxl.red + cur_pxl.green + cur_pxl.blue) / 3;
389:  	 (*new_img).data[row][col].blue =
390:  	   (cur_pxl.red + cur_pxl.green + cur_pxl.blue) / 3;
391:        }
392:  }
393:  
394:  
395:  /* =================================================================
396:   * Callback functions.
397:   *
398:   * color = displayed graphics in window
399:   * menu = menu event handling
400:   * keyboard = deyboard event handling
401:   * ----------------------------------------------------------------- */
402:  void color(void)
403:  {
404:    /*glClear (GL_COLOR_BUFFER_BIT);*/
405:     
406:     /*  printf("\nDrawing Original image...\n");*/
407:    showColor(img_cur);
408:     
409:    /*glFlush();*/
410:  }
411:  
412:  #define RESTART 0
413:  #define CAMERA_CORRECTION 1
414:  #define X2_C_CORR 2
415:  #define NEW_CORR 3
416:  #define COLOR_TO_GRAY 4
417:  
418:  void menu(int selection)
419:  {
420:     if(selection == RESTART)   
421:     {
422:        memcpy(img1, img0, sizeof(PGMImage));
423:        img_cur = img0;
424:     }
425:     if(selection == CAMERA_CORRECTION)
426:     {
427:        printf("Starting camera correction\n");
428:        camera_correction(img1, img0);
429:        img_cur = img1;
430:      }
431:      if(selection == X2_C_CORR)
432:      {
433:         printf("Starting camera correction\n");
434:         camera_correction(img1, img0);
435:         camera_correction(img2, img1);
436:         img_cur = img2;
437:      }
438:      if(selection == NEW_CORR)
439:      {
440:         new_corr(img1, img0);
441:         img_cur = img1;
442:      }
443:      if(selection == COLOR_TO_GRAY)
444:      {
445:         color_to_gray(img1, img0);
446:         img_cur = img1;
447:      }
448:      /*glClear (GL_COLOR_BUFFER_BIT);*/
449:      showColor(img_cur);
450:      glutPostRedisplay();
451:  }
452:  
453:  void keyboard(unsigned char key, int x, int y)
454:  { 
455:     switch (key)
456:     {
457:        case 27: 
458:           exit(0);
459:           break;
460:     }
461:  }
462:    
463:  /* =================================================================
464:   * init - initializes graphics viewport
465:   *
466:   * You should not have to change this function for the first few
467:   * projects we have. It will become more important when we move to
468:   * 3D graphics.
469:   * ----------------------------------------------------------------- */
470:  void init (void)
471:  {
472:    
473:  /*
474:   * select clearing color - white
475:   */
476:     glClearColor (1.0, 1.0, 1.0, 0.0);
477:  
478:  /*
479:   * initialize viewport values
480:   */
481:     glMatrixMode(GL_PROJECTION);
482:     glLoadIdentity();
483:     glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
484:  
485:     /*add menus*/
486:     glutCreateMenu(menu);
487:     glutAddMenuEntry("Restart", RESTART);
488:     glutAddMenuEntry("Camera Correction", CAMERA_CORRECTION);
489:     glutAddMenuEntry("2x C. Corr.", X2_C_CORR);
490:     glutAddMenuEntry("new corr", NEW_CORR);
491:     glutAddMenuEntry("color to gray", COLOR_TO_GRAY);
492:     glutAttachMenu(GLUT_RIGHT_BUTTON);
493:  }
494:   
495:  int main(int argc, char** argv)
496:  {
497:     char PGMfileName[MAX_FILE_LENGTH];
498:     
499:     int WindowID;
500:  
501:     int i;  /*looping variable*/
502:      
503:     /*parse the command line*/  
504:     if(argc == 1)
505:     {
506:        printf("To few parameters.\n");
507:        printf("Usage: research < file.pgm >\n");
508:        exit(1);
509:     }
510:     else if(argc == 2)
511:        strcpy(PGMfileName, argv[1]);
512:     else
513:     {
514:        printf("To many parameters.\n");
515:        printf("Usage: research < file.pgm >\n");
516:        exit(1);
517:     }
518:  /*
519:   * Read in image file. - note: sets our global values, too.
520:   * ----------------------------------------------------------------- */
521:               
522:     img0 = (PGMImage*) malloc(sizeof(PGMImage));
523:     getPGMfile(PGMfileName, img0);
524:     HSIZE = (*img0).width;
525:     VSIZE = (*img0).height;
526:     MVAL = (*img0).maxVal;
527:  
528:     img_cur = img0; /*VERY IMPORTANT to set this*/
529:              
530:     /*allocate memory for second image*/
531:     img1 = (PGMImage*) malloc(sizeof(PGMImage));
532:     memcpy(img1, img0, sizeof(PGMImage));
533:     /*(*img1).width = HSIZE;
534:     (*img1).height = VSIZE;
535:     (*img1).maxVal = 255;*/
536:               
537:     img2 = (PGMImage*) malloc(sizeof(PGMImage));
538:     memcpy(img2, img0, sizeof(PGMImage));
539:              
540:  /*
541:   * Initialize the glut package.
542:   * ----------------------------------------------------------------- */
543:     glutInit(&argc, argv);
544:     glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
545:  /*           
546:   * Define a new window (its size, position and title).
547:   * ----------------------------------------------------------------- */
548:        glutInitWindowSize (HSIZE, VSIZE);  /*size*/
549:        glutInitWindowPosition (10, 10);    /*position*/
550:        WindowID = glutCreateWindow (PGMfileName); /*title*/
551:        glutSetWindow(WindowID);
552:        glutDisplayFunc(color);
553:        
554:  /*  
555:   * Call our init function to define viewing parameters.
556:   * ----------------------------------------------------------------- */
557:     init ();
558:        
559:     glutKeyboardFunc(keyboard); 
560:     glutMainLoop();
561:  
562:  /*  
563:   * When we reach here, we've left the event loop and are ready to
564:   * exit.
565:   * ----------------------------------------------------------------- */
566:     return 0;
567:  }
568:  
569:  
570:  
571:  
572:  
573:  
574:  
575:  
576:  
577:  
578:  
579:  
580: