1:  #include "linked_list.h"
2:  #include "chaincode.h"
3:  #include "research.h"
4:  #include "pgm.h"
5:  #include <string.h>
6:  
7:  /*******Evil globals*********************************/
8:  
9:  int cur_threash_val; /*for speed optimization of chain code recursion*/
10:  int back_ground;
11:  
12:  const RGB_INT chaincode_color = {255, 255, 255};
13:  
14:  /******CHAIN CODE************************************************
15:  ****************************************************************/
16:  
17:  /*returns TRUE if the chain code loops around itself, otherwise false*/
18:  int checkCode(list_info* list_pointers, int x_current, int y_current,
19:  	      int x_check, int y_check, int dir)
20:  {
21:     list_info temp;
22:  
23:     ToFirst(list_pointers);
24:  
25:     while(!AtEnd(list_pointers))
26:     {
27:        /*needed to check two nodes ahead in following if*/
28:        temp = RetrieveNextNode(list_pointers);
29:  
30:        /*check two consecutive points*/
31:        if((RetrieveInfo(list_pointers).location.x == x_current) &&
32:           (RetrieveInfo(list_pointers).location.y == y_current) &&
33:           (RetrieveInfo(list_pointers).code == dir) &&
34:           (RetrieveNextInfo(list_pointers).location.x == x_check) &&
35:           (RetrieveNextInfo(list_pointers).location.y == y_check) &&
36:  	 (RetrieveNextNode(&temp).cur)) /*don't count the new node already*/
37:        {
38:           return TRUE; /*The chain code end looped around*/
39:        }
40:        else
41:  	/*currentNode = RetrieveNextNode(list_pointers);*/
42:          Advance(list_pointers);
43:     }
44:     return FALSE;
45:  }
46:  
47:  /*
48:  Preconditions:
49:  1st parameter: integer value containing the current x coordinate.
50:  2nd parameter: integer value containing the current y coordinate.
51:  3rd parameter: pointer to the pgm image being used.
52:  Postconditions:  return true if pixel is deemed boarder of object, false
53:     otherwise.*/
54:  int checkThings(int x_check, int y_check, PGMImage *img)
55:  {
56:  
57:     /*check for being in bounds*/
58:     if((x_check < 0) || (y_check < 0) || (x_check >= (*img).width) ||
59:        (y_check >= (*img).height))
60:        return FALSE;
61:  
62:     /*tests if the next pixel is greater than the threashing value.  This 
63:        value (cur_threash_val) should be set to the return value of 
64:        img_pxl_avg().  Also, checks if the pixel is considered in the background
65:        or forground agains the value in back_ground.  If so, return true to
66:        indicate create new node.*/
67:     if((rgb_avg((*img).data[y_check][x_check]) > cur_threash_val)
68:        && (back_ground < 0))
69:        return TRUE;   
70:  
71:     /*same thing as above, just for things less than, rathur than greater than*/
72:     if((rgb_avg((*img).data[y_check][x_check]) < cur_threash_val)
73:       && (back_ground > 0))
74:        return TRUE;
75:  
76:     return FALSE;
77:  }  
78:  
79:  chain neighborhood_point(int x_coord, int y_coord, int dir)
80:  {
81:     chain temp = {{x_coord, y_coord}, dir};
82:  
83:     if(dir == EAST)
84:        temp.location.x++;
85:     else if(dir == NORTHEAST)
86:     {
87:        temp.location.x++;
88:        temp.location.y++;
89:     }
90:     else if(dir == NORTH)
91:        temp.location.y++;
92:     else if(dir == NORTHWEST)
93:     {
94:        temp.location.x--;
95:        temp.location.y++;
96:     }
97:     else if(dir == WEST)
98:        temp.location.x--;
99:     else if(dir == SOUTHWEST)
100:     {
101:        temp.location.x--;
102:        temp.location.y--;
103:     }
104:     else if(dir == SOUTH)
105:        temp.location.y--;
106:     else if(dir == SOUTHEAST)
107:     {
108:        temp.location.x++;
109:        temp.location.y--;
110:     }
111:  
112:     return temp;
113:  }
114:  
115:  /*determines the chain code for a starting pixel*/
116:  /*this chain code uses 8 connectivity*/
117:  /*Note: There are many different coordinate systems at work in this function.*/
118:  /*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
119:  /*   top left is (0, 0).  If it looks strange, look harder!!!*/
120:  /*Preconditions:
121:  1st parameter: pointer to the pgm image being used.
122:  2nd parameter: integer value containing the current x coordinate.
123:  3rd parameter: integer value containing the current y coordinate.
124:  4th parameter: integer value containing the current direction code.
125:  5th parameter: pointer to the last node of the chain code.
126:  6th parameter: pointer to the first node of the chain code.*/
127:  /*This function assumes the (0, 0) point is in the lower left*/
128:           
129:  int chaincode(PGMImage *img, int x, int y, int dir, list_info* list_pointers)
130:  {
131:     int i; /*loop counting*/
132:     int next /*next direction to check*/, finished /*finished flag*/;
133:     chain next_point_to_check; /*next_point_to_check What else?*/
134:  
135:     next = (dir + 5) % 8; /*better initail choice?*/
136:  
137:  /*printf("next: %d  x: %d  y: %d\n", next, x, y);*/
138:     for(i = 0; i < 8; i++)
139:     {
140:        /*determine the next point to check*/
141:        next_point_to_check = neighborhood_point(x, y, next);
142:  
143:        if(checkThings(next_point_to_check.location.x,
144:  		     next_point_to_check.location.y, img))
145:        {
146:  /*setCPixel(next_point_to_check.location.x, next_point_to_check.location.y,
147:    chaincode_color);*/
148:  
149:  	 /*create the new node to go last in the chain*/
150:           InsertAfter(next_point_to_check, list_pointers);
151:           /*Advance(list_pointers);*/
152:  
153:  	 /*if the next chaincode function in the recursion or the current state
154:           is the final state of the the chain code; recursively returns DONE
155:           back through all the levels to stop the chain code.*/
156:  	 if(checkCode(list_pointers, x, y, next_point_to_check.location.x,
157:  		    next_point_to_check.location.y, dir))
158:  	 {
159:  	    return NONE;
160:  	 }
161:  
162:  	 if(NONE == chaincode(img, next_point_to_check.location.x,
163:  			      next_point_to_check.location.y, next,
164:  			      list_pointers))
165:  	    return NONE;
166:        }
167:  
168:        /*set next for next iteration*/
169:        next = (next + 1) % 8;
170:     }
171:     return FALSE;         
172:  }
173:  
174:  /*returns true if the point is already in one of the chains, false otherwise*/
175:  int alreadyFound(int initThreashFlag, int i, int j, list_info* found)
176:  {
177:     int k; /*loop counting*/
178:     list_info temp; /*temporary node pointer*/
179:  
180:     /*while there are codes to check...*/
181:     for(k = 0; (k < MAX_NUMBER_OF_CHAINS) && (found[k].head); k++)
182:     {
183:        memcpy(&temp, &found[k], sizeof(list_info));
184:        while(!AtEnd(&temp)) /*...check them.*/
185:        {
186:  	 /*if point has already been found*/
187:  	 if((RetrieveInfo(&temp).location.x == i) &&
188:  	    (RetrieveInfo(&temp).location.y == j))
189:  	 {
190:  	    return TRUE;
191:  	    break;
192:  	 }
193:  	 Advance(&temp);
194:        }
195:        /*Don't forget the last point!!!*/
196:        if((RetrieveInfo(&temp).location.x == i) &&
197:  	 (RetrieveInfo(&temp).location.y == j))
198:        {
199:  	return TRUE;
200:  	break;
201:        }
202:     }
203:     
204:     return FALSE;
205:  }
206:  
207:  /*saves a chain code to file.  Was usefull during debuging now is just
208:    a cool thing to leave in*/
209:  /*1st: pointer to beginning of a chaincode
210:  2nd: the index of the chain code for destiqushing the 'chain' files*/
211:  void saveChainCode(list_info save_chain, int count)
212:  {
213:     char filename[12];
214:     FILE* outfile;
215:     sprintf(filename, "chain%d", count);
216:     outfile = fopen(filename, "w");   /*output file for chaincode*/
217:  /*printf("Writing chain code to file %s.\n", filename);*/
218:  
219:     ToFirst(&save_chain);
220:     while(!AtEnd(&save_chain))
221:     {
222:     
223:        fprintf(outfile, "%d  %d  %d\n", RetrieveInfo(&save_chain).location.x,
224:  	      RetrieveInfo(&save_chain).location.y,
225:  	      RetrieveInfo(&save_chain).code);
226:        Advance(&save_chain);
227:     }
228:     fclose(outfile);
229:  }
230:  
231:  
232:  
233:  /*frees the memory that the chain code(s) are using*/
234:  /*aogccp = address of global chain code pointer*/
235:  /*upon success the pointer whose address is passed in is set to NULL.*/
236:  void free_chaincodes(list_info** aogccp)
237:  {
238:     int i; /*loop counting*/
239:     list_info temp, to_free;
240:     
241:     /*for each chaincode, free all of the nodes.*/
242:     for(i = 0; aogccp && (*aogccp) && (*aogccp)[i].cur && i < MAX_CHAINS; i++)
243:     {
244:       FreeList(&(*aogccp)[i]);
245:     }
246:  
247:     free(*aogccp); /*free the array of pointers to chaincodes*/
248:  
249:     *aogccp = NULL; /*set global to NULL indicating there isn't a chaincode*/
250:  }
251:  
252:  
253:  list_info* showChain(PGMImage *original, list_info** original_chains)
254:  {
255:     int i, j, k;  /*loop counting*/
256:     int count = 0; /*array index holder*/
257:     int initThreashFlag = img_pxl_avg(original);
258:     list_info *the_lists;
259:  
260:     /*If the_lists point to an array of list_infos (chaincodes), then free
261:       the memory before allocating more.  If the_lists is NULL, then there
262:       aren't allocated chaincodes and nothing will change.*/
263:     free_chaincodes(original_chains);
264:      
265:     /*allocate an array of pointers to chainCodes, then initalize their
266:       values to NULL*/
267:     the_lists = (list_info*)
268:       malloc(MAX_NUMBER_OF_CHAINS * sizeof(list_info));
269:     memset(the_lists, 0, MAX_NUMBER_OF_CHAINS * sizeof(list_info));
270:  
271:     cur_threash_val = initThreashFlag; /*set global variables*/
272:     back_ground = background(initThreashFlag, original);
273:  
274:     /*search image until a pixel is found with threasholded value of the
275:     object.  i & j will then contain the starting coordinate.*/
276:     for(i = 0; i < (*original).width; i++) /*x direction*/
277:     {
278:        for(j = (*original).height - 1; j >= 0; j--) /*y direction*/
279:        {
280:           /*skip to the next iteration if pixel isn't "good" enough*/
281:           if(!checkThings(i, j, original))
282:              continue;
283:  
284:           /*skip to the next iteration, which will be at the top of the next
285:             collumn.  This is true when the pixel has already been found in
286:  	   one of the chain codes.*/
287:           else if(alreadyFound(initThreashFlag, i, j, the_lists))
288:  	    break;
289:  
290:           else
291:           {
292:  /*printf("chaincode: %d\n", count);*/
293:              /*printf("The starting coordinate is (x, y): (%d, %d)\n", i, j);*/
294:              
295:              /*Initalize the lists*/
296:  	    InitList(&the_lists[count]);
297:  
298:              chaincode(original, i, j, SOUTHEAST, &the_lists[count]);
299:  
300:  	    if(the_lists[count].cur != NULL)/*avoid writing zero length chain*/
301:  	    {
302:  	       /*send the chaincode data to file, usefull for debuggin.*/
303:  	       saveChainCode(the_lists[count], count);
304:    	       count++; /*advance the beginning counter*/
305:  	    }
306:  
307:  	    /*force end of loops, leaving code when finished looping
308:  	      to still execute, since the number of chains is filled to max.*/
309:  	    if(count >= MAX_NUMBER_OF_CHAINS)
310:  	       i = (*original).width;
311:  
312:              break; /*check the next collumn*/
313:           }
314:        }   
315:     }
316:     printf("\nDone finding chain code(s).  %d were found.\n", count);
317:     *original_chains = the_lists;
318:     return the_lists;
319:  }