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