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