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