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: