[GRASS-SVN] r52053 - grass-addons/grass7/imagery/i.segment

svn_grass at osgeo.org svn_grass at osgeo.org
Tue Jun 12 16:03:05 PDT 2012


Author: momsen
Date: 2012-06-12 16:03:03 -0700 (Tue, 12 Jun 2012)
New Revision: 52053

Added:
   grass-addons/grass7/imagery/i.segment/open_files.c
Modified:
   grass-addons/grass7/imagery/i.segment/create_isegs.c
   grass-addons/grass7/imagery/i.segment/iseg.h
   grass-addons/grass7/imagery/i.segment/main.c
   grass-addons/grass7/imagery/i.segment/parse_args.c
   grass-addons/grass7/imagery/i.segment/write_output.c
Log:


Modified: grass-addons/grass7/imagery/i.segment/create_isegs.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/create_isegs.c	2012-06-12 21:45:12 UTC (rev 52052)
+++ grass-addons/grass7/imagery/i.segment/create_isegs.c	2012-06-12 23:03:03 UTC (rev 52053)
@@ -16,7 +16,7 @@
 
     int successflag = 1;
 
-    /* method specific parameter set up and memory allocation */
+    /* TODO consider if there are _method specific_ parameter set up and memory allocation, should that happen here? */
 
     if (functions->method == 1) {	/*region growing */
 
@@ -24,28 +24,24 @@
     }
 
     /*TODO: implement outer loop to process polygon interior, then all remaining pixels */
-    /* This loop could go in here, or outside in main (only make segmentation file for what is currently being processed.) */
+    /* This loop could go in here, or in main to contain open/create/write to reduced memory reqs.  But how merge the writes? */
 
     G_debug(1, "Threshold: %g", functions->threshold);
     G_debug(1, "segmentation method: %d", functions->method);
 
 
     if (functions->method == 0)
-	successflag = io_debug(files, functions);	/* TODO: why does it want &files in main, but files here ??? */
+	successflag = io_debug(files, functions);	/* TODO: why does it want `&files` in main, but `files` here ??? */
     else if (functions->method == 1) {
 	G_debug(1, "starting region_growing()");
 	successflag = region_growing(files, functions);
     }
-    if (successflag != 0)
-	G_fatal_error("Error creating segments");
 
     /* end outer loop for processing polygons */
 
     /* clean up */
 
-    /* should there be a free() for every malloc?  Or only the large ones? */
-
-    return 0;
+    return successflag;
 }
 
 int io_debug(struct files *files, struct functions *functions)
@@ -56,7 +52,7 @@
 
     G_verbose_message("writing fake data to segmentation file");
     for (row = 0; row < files->nrows; row++) {
-	G_percent(row, files->nrows, 1);	/*this didn't get displayed in the output??? Does it get erased when done? */
+	G_percent(row, files->nrows, 1);	/* TODO this didn't get displayed in the output??? Does it get erased when done? */
 	for (col = 0; col < files->ncols; col++) {
 	    /*files->out_val[0] = files->out_val[0]; *//*segment number *//* just copying the map for testing. */
 	    files->out_val[0] = col + row;
@@ -65,8 +61,10 @@
 	}
     }
 
-    /* TODO: free memory */
+    /* spot to test things... */
 
+
+
     return 0;
 }
 
@@ -83,7 +81,7 @@
     /* Ri = current focus segment
      * Rk = Ri's most similar neighbor
      * Rkn = Rk's neighbors
-     * Rin = Ri's neigbors (as pixels or segments ?!?
+     * Rin = Ri's neigbors (as pixels or segments ?) currently as pixels, so repeat calculations are made when multiple neighbors in same segment
      */
 
     /* lets get this running, and just use fixed dimension arrays for now.  t is limited to 90, segments will be small. */
@@ -95,21 +93,23 @@
     G_verbose_message("Running region growing algorithm");
 
     t = 0;
+    files->candidate_count = 0;
 
     do {
-	/* for loop on t to slowly lower threshold. also check that endflag=0 */
+	/* do while loop on t to slowly lower threshold. also check that endflag==0 */
 
-	threshold = functions->threshold;	/* when implement t loop, this will be a function of t. */
+	G_debug(1,
+		"#############   Starting outer do loop! t = %d ###############",
+		t);
 
+	threshold = functions->threshold;	/* TODO, consider making this a function of t. */
+
 	endflag = 1;
 
-
 	/* Set candidate flag to true/1 for all pixels TODO: for polygon group, need to just set to true for those being processed */
 
-	/*      for (row = 0; row < files->nrows; row++) {
-	   for (col = 0; col < files->ncols; col++) {   -----need to deal with edges.... */
-	for (row = 1; row < files->nrows - 1; row++) {
-	    for (col = 1; col < files->ncols - 1; col++) {
+	for (row = 0; row < files->nrows; row++) {
+	    for (col = 0; col < files->ncols; col++) {
 		segment_get(&files->out_seg, (void *)files->out_val, row, col);	/*need to get, since we only want to change the flag, and not overwrite the segment value. */
 		/* TODO: if we are starting from seeds...and only allow merges between unassigned pixels
 		 *  and seeds/existing segments, then this needs an if (and will be very inefficient)
@@ -117,18 +117,30 @@
 		files->out_val[1] = 1;	/*candidate pixel flag */
 		segment_put(&files->out_seg, (void *)files->out_val, row,
 			    col);
+
+		files->candidate_count++;	/*TODO this assumes full grid with no null or mask!! But need something to prevent "pathflag" infinite loop */
+
 	    }
 	}
-	G_debug(1, "Starting to process candidate pixels");
+	G_debug(1, "Starting to process %d candidate pixels",
+		files->candidate_count);
+
 	/*process candidate pixels */
 
 	/*check each pixel, start the processing only if it is a candidate pixel */
 	for (row = 0; row < files->nrows; row++) {
 	    for (col = 0; col < files->ncols; col++) {
-		segment_get(&files->out_seg, (void *)files->out_val, row,
-			    col);
-		if (files->out_val[1] == 1) {	/* out_val[1] is the candidate pixel flag */
 
+		G_verbose_message("Completion for pass number %d: ", t);
+		G_percent(row, files->nrows, 1);	/*this didn't get displayed in the output??? Does it get erased when done? */
+
+		G_debug(1,
+			"Next starting pixel from next row/col, not from Rk");
+		segment_get(&files->out_seg, (void *)files->out_val, row, col);	/*TODO small time savings - if candidate_count reaches zero, bail out of these loops too? */
+		if (files->out_val[1] == 1) {	/* out_val[1] is the candidate pixel flag, want to process the 1's */
+
+		    /*  ... need to switch to lists/stacks/maps... */
+
 		    /*need to empty/reset Ri, Rn, and Rk */
 		    /* TODO: this will be different when Ri is different data structure. */
 		    for (n = 0; n < 100; n++) {
@@ -137,95 +149,151 @@
 			}
 		    }
 		    Rin_count = Rkn_count = Rk_count = 0;
+
+		    /* First pixel in Ri is current pixel.  We may add more later if it is part of a segment */
 		    Ri_count = 1;	/*we'll have the focus pixel to start with. */
 
-		    /* First pixel in Ri is current pixel.  We may add more later if it is part of a segment */
 		    Ri[0][0] = row;
 		    Ri[0][1] = col;
-		    /* Ri_seg = files->out_val[0]; don't need this here -have it in merge_segments() *//* out_val[0] is segment ID, we still have data from call to check the flag. *//* TODO: if seperate segment ID from flag, need to get this value. */
 
 		    pathflag = 1;
 
-		    while (pathflag == 1) {	/*if don't find mutual neighbors on first try, will use Rk as next Ri. */
-			G_debug(1, "just before find_segment_neighbors(Ri)");
-			if (find_segment_neighbors
-			    (Ri, Rin, Ri_count, Rin_count, files,
-			     functions) != 0) {
-			    G_debug(1, "Couldn't find neighbors");	/*this could happen if there is a pixel surrounded by pixels that have already been processed */
-			    pathflag = 0;
-			    Ri_count = 0;
-			    set_candidate_flag(Ri, 0, files);	/* TODO: error trap? */
-			}
-			else {	/*found neighbors, go ahead until find mutually agreeing neighbors */
-			    G_debug(1, "Found neighbors");
-			    /* find Ri's most similar neighbor */
-			    Rk_id = -1;
-			    Ri_similarity = LDBL_MAX;	/* set current similarity to max value */
-			    segment_get(&files->bands_seg, (void *)files->bands_val, Ri[0][0], Ri[0][1]);	/* current segment values */
+		    //      while (pathflag == 1 && files->candidate_count > 0) {   /*if don't find mutual neighbors on first try, will use Rk as next Ri. */
 
-			    for (n = 0; n < Rin_count; n++) {	/* for each of Ri's neighbors */
-				tempsim = (*functions->calculate_similarity) (Ri[0], Rin[n], files, functions);	/*TODO: does this pass just the single point, row/col ???? */
-				if (tempsim < Ri_similarity) {
-				    Ri_similarity = tempsim;
-				    Rk_id = n;
-				}
+		    G_debug(1, "Next starting pixel: row, %d, col, %d",
+			    Ri[0][0], Ri[0][1]);
+
+		    /* Setting Ri to be not a candidate allows using "itself" when at edge of raster.
+		     * Otherwise need to use a list/count/something to know the number of pixel neighbors */
+		    set_candidate_flag(Ri, 0, 0, files);	/* TODO: error trap? */
+		    G_debug(1, "line 165, \t\t\t\tcc = %d",
+			    files->candidate_count);
+
+
+		    /* find segment neighbors */
+		    if (find_segment_neighbors
+			(Ri, Rin, &Ri_count, &Rin_count, files,
+			 functions) != 0) {
+			G_fatal_error("find_segment_neighbors() failed");
+		    }
+
+		    if (Rin_count == 0) {
+			G_debug(1, "2a, Segment had no valid neighbors");	/*this could happen if there is a segment surrounded by pixels that have already been processed */
+			pathflag = 0;
+			Ri_count = 0;
+			set_candidate_flag(Ri, Ri_count, 0, files);	/* TODO: error trap? */
+			files->candidate_count++;	/* already counted out Ri[0]; */
+			G_debug(1, "line 176, \t\t\t\tcc = %d",
+				files->candidate_count);
+		    }
+		    else {	/*found neighbors, go ahead until find mutually agreeing neighbors */
+
+			G_debug(1, "2b, Found Ri's pixels");
+			/*print out neighbors */
+			for (n = 0; n < Ri_count; n++)
+			    G_debug(1, "Ri %d: row: %d, col: %d", n, Ri[n][0],
+				    Ri[n][1]);
+
+			G_debug(1, "2b, Found Ri's neighbors");
+			/*print out neighbors */
+			for (n = 0; n < Rin_count; n++)
+			    G_debug(1, "Rin %d: row: %d, col: %d", n,
+				    Rin[n][0], Rin[n][1]);
+
+			/* find Ri's most similar neighbor */
+			Rk_id = -1;
+			Ri_similarity = LDBL_MAX;	/* set current similarity to max value */
+			segment_get(&files->bands_seg, (void *)files->bands_val, Ri[0][0], Ri[0][1]);	/* current segment values */
+
+			for (n = 0; n < Rin_count; n++) {	/* for each of Ri's neighbors */
+			    tempsim = (*functions->calculate_similarity) (Ri[0], Rin[n], files, functions);	/*TODO: does this pass just the single point, row/col ???? */
+			    G_debug(1,
+				    "simularity = %g for neighbor %d: row: %d, col %d.",
+				    tempsim, n, Rin[n][0], Rin[n][1]);
+			    if (tempsim < Ri_similarity) {
+				Ri_similarity = tempsim;
+				Rk_id = n;
 			    }
+			}
 
-			    if (Rk_id >= 0 && Ri_similarity < threshold) {	/* small TODO: should this be < or <= for threshold? */
-				/*we'll have the neighbor pixel to start with. */
-				Rk_count = 1;
-				Rk[0][0] = Rin[Rk_id][0];
-				Rk[0][1] = Rin[Rk_id][1];
+			G_debug(1,
+				"Lowest Ri_similarity = %g, for neighbor pixel Rk_id (n) = %d",
+				Ri_similarity, Rk_id);
 
-				/* Rkn = Ri; *//* we know Ri should be a neighbor of Rk *//*Todo: is there a way to skip similarity calculations on these?  keep a count, and pop them before doing the similarity check? */
-				find_segment_neighbors(Rk, Rkn, Rk_count, Rkn_count, files, functions);	/* data structure for Rk's neighbors, and pixels in Rk if we don't already have it */
+			if (Rk_id >= 0 && Ri_similarity < threshold) {	/* small TODO: should this be < or <= for threshold? */
+			    /* we'll have the neighbor pixel to start with. */
+			    G_debug(1, "3a: Working with Rk");
+			    Rk_count = 1;
+			    Rk[0][0] = Rin[Rk_id][0];
+			    Rk[0][1] = Rin[Rk_id][1];
 
-				/*find Rk's most similar neighbor */
-				Rk_similarity = Ri_similarity;	/*Ri gets first priority - ties won't change anything, so we'll accept Ri and Rk as mutually best neighbors */
-				segment_get(&files->bands_seg, (void *)files->bands_val, Rk[0][0], Rk[0][1]);	/* current segment values */
+			    /* Rkn = Ri; *//* we know Ri should be a neighbor of Rk *//*Todo: is there a way to skip similarity calculations on these?  keep a count, and pop them before doing the similarity check? */
+			    find_segment_neighbors(Rk, Rkn, &Rk_count, &Rkn_count, files, functions);	/* data structure for Rk's neighbors, and pixels in Rk if we don't already have it */
 
-				for (n = 0; n < Rkn_count; n++) {	/* for each of Rk's neighbors */
-				    tempsim =
-					functions->calculate_similarity(Rk[0],
-									Rkn
-									[n],
-									files,
-									functions);
-				    if (tempsim < Rk_similarity) {
-					Rk_similarity = tempsim;
-					break;	/* exit for Rk's neighbors loop here, we know that Ri and Rk aren't mutually best neighbors */
-				    }
-				}
+			    G_debug(1, "Found Rk's pixels");
+			    /*print out neighbors */
+			    for (n = 0; n < Rk_count; n++)
+				G_debug(1, "Rk %d: row: %d, col: %d", n,
+					Rk[n][0], Rk[n][1]);
 
-				if (Rk_similarity == Ri_similarity) {	/* so they agree, both are mutually most similar neighbors */
-				    /* TODO: put these steps in merge_segments(Ri, Rk) function?  */
-				    merge_values(Ri, Rk, Ri_count, Rk_count, files);	/* TODO error trap */
-				    endflag = 0;	/* we've made at least one merge, so need another t iteration */
-				    pathflag = 0;	/* go to next row,column pixel - end of Rk -> Ri chain since we found mutual best neighbors */
+			    G_debug(1, "Found Rk's neighbors");
+			    /*print out neighbors */
+			    for (n = 0; n < Rkn_count; n++)
+				G_debug(1, "Rkn %d: row: %d, col: %d", n,
+					Rkn[n][0], Rkn[n][1]);
+
+			    /*find Rk's most similar neighbor */
+			    Rk_similarity = Ri_similarity;	/*Ri gets first priority - ties won't change anything, so we'll accept Ri and Rk as mutually best neighbors */
+			    segment_get(&files->bands_seg, (void *)files->bands_val, Rk[0][0], Rk[0][1]);	/* current segment values */
+
+			    for (n = 0; n < Rkn_count; n++) {	/* for each of Rk's neighbors */
+				tempsim = functions->calculate_similarity(Rk[0], Rkn[n], files, functions);	/*TODO: need an error trap here, if something goes wrong with calculating similarity? */
+				if (tempsim < Rk_similarity) {
+				    Rk_similarity = tempsim;
+				    break;	/* exit for Rk's neighbors loop here, we know that Ri and Rk aren't mutually best neighbors */
 				}
-				else {	/* they weren't mutually best neighbors */
-				    set_candidate_flag(Ri, 0, files);	/* remove Ri from candidate pixels (set flag) */
+			    }
 
-				    /* Use Rk as next Ri:   this is the eCognition technique.  Seems this is a bit faster, we already have segment membership pixels */
-				    Ri_count = Rk_count;
-				    /* Ri = &Rk; *//* TODO fast/correct way to use arrays and pointers? Ri now will just point to Rk? */
-				    /* at beginning, when initialize Rk ` Rk[n][m] = 0 ` ?? with that just remove the Rk pointer, and leave Ri pointing to the original Rk data? */
-				    for (n = 0; n < 100; n++) {	/*TODO shortcut code...get rid of this... */
-					for (m = 0; m < 2; m++) {
-					    Ri[n][m] = Rk[n][m];
-					}
-				    }
+			    if (Rk_similarity == Ri_similarity) {	/* so they agree, both are mutually most similar neighbors, none of Rk's other neighbors were more similar */
+				/* TODO: put these steps in merge_segments(Ri, Rk) function?  */
+				merge_values(Ri, Rk, Ri_count, Rk_count, files);	/* TODO error trap */
+				endflag = 0;	/* we've made at least one merge, so need another t iteration */
+				pathflag = 0;	/* go to next row,column pixel - end of Rk -> Ri chain since we found mutual best neighbors */
+			    }
+			    else {	/* they weren't mutually best neighbors */
+				G_debug(1,
+					"Ri was not Rk's best neighbor, Ri_sim: %g, Rk_sim, %g",
+					Ri_similarity, Rk_similarity);
 
-				}
-			    }	/*end if Rk exists and < threshold */
-			}	/* end else - Ri did have neighbors */
-		    }		/*end pathflag do loop */
+				/* did this at beginning of trail loop */
+				set_candidate_flag(Ri, Ri_count, 0, files);	/* remove all Ri members from candidate pixels (set flag) */
+				files->candidate_count++;	/* add one back, we had already set Ri[0] flag at the beginning. */
+				G_debug(1, "line 247, \t\t\t\tcc = %d",
+					files->candidate_count);
+				//~ /* Use Rk as next Ri:   this is the eCognition technique.  Seems this is a bit faster, we already have segment membership pixels */
+				//~ Ri_count = Rk_count;
+				//~ /* Ri = &Rk; *//* TODO fast/correct way to use arrays and pointers? Ri now will just point to Rk? */
+				//~ /* at beginning, when initialize Rk ` Rk[n][m] = 0 ` ?? with that just remove the Rk pointer, and leave Ri pointing to the original Rk data? */
+				//~ for (n = 0; n < 100; n++) {     /*TODO shortcut code...get rid of this... */
+				//~ for (m = 0; m < 2; m++) {
+				//~ Ri[n][m] = Rk[n][m];
+				//~ }
+				//~ }
+
+			    }
+			}	/*end if Rk exists and < threshold */
+			else
+			    G_debug(1,
+				    "3b Rk didn't didn't exist or similarity was > threshold");
+		    }		/* end else - Ri did have neighbors */
+		    //          }           /*end pathflag do loop */
 		}		/*end if pixel is candidate pixel */
 	    }			/*next column */
 	}			/*next row */
 
 	/* finished one pass for processing candidate pixels */
 
+	G_debug(1, "Finished one pass, t was = %d", t);
 	t++;
     } while (t < 90 && endflag == 0);
     /*end t loop */
@@ -235,11 +303,11 @@
     return 0;
 }
 
-int find_segment_neighbors(int Ri[][2], int Rin[][2], int seg_count,
-			   int segn_count, struct files *files,
+int find_segment_neighbors(int Ri[][2], int Rin[][2], int *seg_count,
+			   int *segn_count, struct files *files,
 			   struct functions *functions)
 {
-    G_debug(1, "in find_segment_neighbors()");
+    //   G_debug(1, "\tin find_segment_neighbors()");
     int n, m, Ri_seg_ID = -1;
 
     /* neighbor list will be a listing of pixels that are neighbors?  Include segment numbers?  Only include unique segments?
@@ -248,78 +316,105 @@
      */
 
 
-    /* Ri could be single pixel or list of pixels. */
-    /* Rin could have a list already, or could be empty ?  Or just the head?  */
+    /* parameter: Ri, current segment membership, could be single pixel or list of pixels. */
+    /* parameter: Rin, neighbor pixels, could have a list already, or could be empty ?  Or just the head of a list?  */
 
-    /*local data structures... but maybe they should be allocated out in the main function, is it really slow to create/free on each pass? */
+    /* TODO local data structures... but maybe they should be allocated out in the main function, is it really slow to create/free on each pass? */
 
-    /* Ri : input parameter, list of pixels in the current segment */
     int to_check[100][2];	/* queue or stack - need to check the neighbors of these pixels */
 
+    /* put no_check in files structure for now... */
     /* int[100][2] no_check;    *//* sorted array or btree: list of pixels (by row / column ?) that have been put into the to_check queue, been processed, or are not candidate pixels */
     /* or use flag for no_check? ... need a better name for this variable??? */
 
-    int pixel_neighbors[8][2];	/* data type?  put in files to allocate memory once? */
+    int val_no_check = -1;	/*value of the no_check flag for the particular pixel. */
 
-    int current_pixel = 0;	/*what data type?  This will be the popped pixel in each loop. */
+    int pixel_neighbors[8][2];	/* TODO: data type?  put in files to allocate memory once? */
 
-    /* functions->pixel_neighbors  ...array, 4 or 8 long.  (Can be 4 or 8 neighbors to each pixel)
-     * functions->num_pn  int, 4 or 8. */
+    int current_pixel = 0;	/* TODO: for now, row index for pixel_neighbors[][].  With linked list will be the popped pixel in each loop. */
 
+    /* Notes, these are in fucntions structure:
+     * functions->num_pn  int, 4 or 8, for number of pixel neighbors */
+
     /*initialize data.... TODO: maybe remember min max row/col that was looked at each time, initialize in open_files, and reset smaller region at end of this functions */
-    G_debug(1, "setting files->no_check to 0...");
-    for (n = 0; n < files->nrows; n++)
-	for (m = 0; n < files->ncols; n++)
-	    files->no_check[n][m] = 0;	/* 0 means should be checked/expanded, 1 means it has already been checked/expanded. */
+    for (n = 0; n < files->nrows; n++) {
+	for (m = 0; m < files->ncols; m++) {
+	    val_no_check = 0;
+	    segment_put(&files->no_check, &val_no_check, n, m);
+	}
+    }
 
-    G_debug(1, "setting to_check to 0");
-
     for (n = 0; n < 100; n++) {
 	for (m = 0; m < 2; m++) {
-	    to_check[n][m] = files->no_check[n][m] = 0;
+	    to_check[n][m] = 0;
 	}
     }
 
     /* Put Ri in to be checked and no check lists (don't expand them if we find them again) */
     /* NOTE: in pseudo code also have a "current segment" list, but think we can just pass Ri and use it directly */
-    G_debug(1, "Setting up Ri... ");
-    for (n = 0; n < seg_count; n++) {
+    for (n = 0; n < *seg_count; n++) {
 	to_check[n][0] = Ri[n][0];
 	to_check[n][1] = Ri[n][1];
 
-	files->no_check[Ri[n][0]][Ri[n][1]] = 1;
+	val_no_check = 1;
+	segment_put(&files->no_check, &val_no_check, Ri[n][0], Ri[n][1]);
+
     }
 
-    /* empty "neighbor" list  Note: in pseudo code, but think we just pass in Rin - it was already initialized, and later could have Ri data available to start from */
+    /* empty "neighbor" list  Note: this step is in pseudo code, but think we just pass in Rin - it was already initialized, and later could have Ri data available to start from */
 
     /* get Ri's segment ID */
     segment_get(&files->out_seg, (void *)files->out_val, Ri[0][0], Ri[0][1]);
-    Ri_seg_ID = files->out_val[1];
-    G_debug(1, "initializing is done, start processing");
-    while (current_pixel >= 0) {	/* change to not empty once there is a stack... */
-	G_debug(1, "current_pixel: %d", current_pixel);
+    Ri_seg_ID = files->out_val[0];
+
+    while (current_pixel >= 0) {	/* change to not empty once there is a linked list... */
+	G_debug(1, "\tfind neighbors(): current_pixel: %d", current_pixel);
 	/* current_pixel = pop next to_check element; */
-	/*syntax for function pointer?  functions->(*find_pixel_neighbors) (to_check[current_pixel], pixel_neighbors, files); */
-	functions->find_pixel_neighbors(to_check[current_pixel],
+
+	G_debug(1,
+		"\tbefore fpn: to_check[current_pixel][0] %d , to_check[current_pixel][1] %d",
+		to_check[current_pixel][0], to_check[current_pixel][1]);
+
+	functions->find_pixel_neighbors(to_check[current_pixel][0],
+					to_check[current_pixel][1],
 					pixel_neighbors, files);
 	current_pixel--;	/* Done using this pixels coords, now check neighbors and add to the lists */
-	G_debug(1, "found pixel neighbors");
-	for (n = 0; n < functions->num_pn; n++) {	/*with pixel neighbors */
-	    if (files->no_check[pixel_neighbors[n][0]][pixel_neighbors[n][1]] == 0) {	/* want to check this neighbor */
-		files->no_check[pixel_neighbors[n][0]][pixel_neighbors[n][1]] = 1;	/* OK, check it, but don't check it again! */
 
+	G_debug(1,
+		"\tafter fpn: to_check[current_pixel][0] %d , to_check[current_pixel][1] %d",
+		to_check[current_pixel][0], to_check[current_pixel][1]);
+
+	/*debug what neighbors were found: */
+	/*      for (n = 0; n < functions->num_pn; n++){
+	   G_debug(1, "\tpixel_neighbors[n][0]: %d, pixel_neighbors[n][1]: %d",  pixel_neighbors[n][0], pixel_neighbors[n][1]);
+	   } */
+
+	for (n = 0; n < functions->num_pn; n++) {	/* with pixel neighbors */
+
+	    segment_get(&files->no_check, &val_no_check,
+			pixel_neighbors[n][0], pixel_neighbors[n][1]);
+	    G_debug(1,
+		    "\twith pixel neighbor %d, row: %d col: %d, val_no_check = %d",
+		    n, pixel_neighbors[n][0], pixel_neighbors[n][1],
+		    val_no_check);
+	    if (val_no_check == 0) {	/* want to check this neighbor */
+		val_no_check = 1;
+		segment_put(&files->no_check, &val_no_check,
+			    pixel_neighbors[n][0], pixel_neighbors[n][1]);
+
 		segment_get(&files->out_seg, (void *)files->out_val, pixel_neighbors[n][0], pixel_neighbors[n][1]);	/*TODO : do I need a second "out_val" data structure? */
 
 		if (files->out_val[1] == 1) {	/* valid candidate pixel */
 
-		    G_debug(1, "files->out_val[0] = %d Ri_seg_ID = %d",
+		    G_debug(1, "\tfiles->out_val[0] = %d Ri_seg_ID = %d",
 			    files->out_val[0], Ri_seg_ID);
 		    if (files->out_val[0] == Ri_seg_ID) {
-			G_debug(1, "puting pixel_neighbor in Ri");
+			G_debug(1, "\tputing pixel_neighbor in Ri");
 			/* put pixel_neighbor[n] in Ri */
-			Ri[seg_count][0] = pixel_neighbors[n][0];
-			Ri[seg_count][1] = pixel_neighbors[n][1];
-			seg_count++;	/* zero index... so increment after save data. */
+			Ri[*seg_count][0] = pixel_neighbors[n][0];
+			Ri[*seg_count][1] = pixel_neighbors[n][1];
+			*seg_count = *seg_count + 1;	/* zero index... Ri[0] had first pixel and set count =1.  increment after save data. */
+			G_debug(1, "\t*seg_count now = %d", *seg_count);
 
 			/* put pixel_neighbor[n] in to_check -- want to check this pixels neighbors */
 			current_pixel++;
@@ -329,9 +424,9 @@
 		    }
 		    else {
 			/* put pixel_neighbor[n] in Rin */
-			Rin[segn_count][0] = pixel_neighbors[n][0];
-			Rin[segn_count][1] = pixel_neighbors[n][1];
-			segn_count++;
+			Rin[*segn_count][0] = pixel_neighbors[n][0];
+			Rin[*segn_count][1] = pixel_neighbors[n][1];
+			*segn_count = *segn_count + 1;
 		    }
 		}		/*end if valid candidate pixel */
 	    }			/*end if for pixel_neighbor was in "don't check" list */
@@ -341,51 +436,51 @@
     return 0;
 }
 
-int find_four_pixel_neighbors(int pixel[2], int pixel_neighbors[][2],
+int find_four_pixel_neighbors(int p_row, int p_col, int pixel_neighbors[][2],
 			      struct files *files)
 {
-    /*
-       G_debug(1,"in find 4 pixel neighbors () ");
-       G_debug(1,"pixel row: %d pixel col: %d", pixel[0], pixel[1]);
-       G_debug(1, "Total rows: %d, total cols: %d", files->nrows, files->ncols); /*check that we have files... */
+    /*   
+       G_debug(1,"\t\tin find 4 pixel neighbors () ");
+       G_debug(1,"\t\tpixel row: %d pixel col: %d", p_row, p_col);
+       G_debug(1, "\t\tTotal rows: %d, total cols: %d", files->nrows, files->ncols); *//*check that we have files... */
 
     /* north */
-    pixel_neighbors[0][1] = pixel[1];
-    if (pixel[0] > 0)
-	pixel_neighbors[0][0] = pixel[0] + 1;
+    pixel_neighbors[0][1] = p_col;
+    if (p_row > 0)
+	pixel_neighbors[0][0] = p_row - 1;
     else
-	pixel_neighbors[0][0] = pixel[0];	/*This is itself, which will be in "already checked" list.  TODO: use null or -1 as flag to skip?  What is fastest to process? */
+	pixel_neighbors[0][0] = p_row;	/*This is itself, which will be in "already checked" list.  TODO: use null or -1 as flag to skip?  What is fastest to process? */
 
     /* east */
-    pixel_neighbors[1][0] = pixel[0];
-    if (pixel[1] < files->ncols)
-	pixel_neighbors[1][1] = pixel[1] + 1;
+    pixel_neighbors[1][0] = p_row;
+    if (p_col < files->ncols - 1)
+	pixel_neighbors[1][1] = p_col + 1;
     else
-	pixel_neighbors[1][1] = pixel[1];
+	pixel_neighbors[1][1] = p_col;
 
     /* south */
-    pixel_neighbors[2][1] = pixel[1];
-    if (pixel[0] < files->nrows)
-	pixel_neighbors[2][0] = pixel[0] - 1;
+    pixel_neighbors[2][1] = p_col;
+    if (p_row < files->nrows - 1)
+	pixel_neighbors[2][0] = p_row + 1;
     else
-	pixel_neighbors[2][0] = pixel[0];
+	pixel_neighbors[2][0] = p_row;
 
     /* west */
-    pixel_neighbors[3][0] = pixel[0];
-    if (pixel[1] < 0)
-	pixel_neighbors[3][1] = pixel[1] - 1;
+    pixel_neighbors[3][0] = p_row;
+    if (p_col > 0)
+	pixel_neighbors[3][1] = p_col - 1;
     else
-	pixel_neighbors[3][1] = pixel[1];
+	pixel_neighbors[3][1] = p_col;
 
     /*TODO: seems there should be a more elegent way to do this... */
     return 0;
 }
 
-int find_eight_pixel_neighbors(int pixel[2], int pixel_neighbors[8][2],
-			       struct files *files)
+int find_eight_pixel_neighbors(int p_row, int p_col,
+			       int pixel_neighbors[8][2], struct files *files)
 {
     /* get the 4 orthogonal neighbors */
-    find_four_pixel_neighbors(pixel, pixel_neighbors, files);
+    find_four_pixel_neighbors(p_row, p_col, pixel_neighbors, files);
 
     /* get the 4 diagonal neighbors */
 
@@ -394,14 +489,15 @@
 }
 
 /* similarity / distance between two points based on their input raster values */
-/* TODO: I pulled getting the a values into the main function, they are stored in files.  Remove a from these parameters */
+/* assumes first point values already saved in files->bands_seg - only run segment_get once for that value... */
+/* TODO: segment_get already happened for a[] values in the main function.  Could remove a[] from these parameters */
 double calculate_euclidean_similarity(int a[2], int b[2], struct files *files,
 				      struct functions *functions)
 {
     double val = 0;
     int n;
 
-    /* get comparison values for point b (got values for a before loop on all neighbors... */
+    /* get values for point b[] */
     segment_get(&files->bands_seg, (void *)files->second_val, b[0], b[1]);
 
     /* euclidean distance, sum the square differences for each dimension */
@@ -417,7 +513,7 @@
 
 int merge_values(int Ri[100][2], int Rk[100][2], int Ri_count, int Rk_count,
 		 struct files *files)
-{				/* I assume this is a weighted mean? */
+{				/* TODO: correct assumption that this should be a weighted mean. */
     int n;
 
     /*get input values, maybe if handle earlier gets correctly this can be avoided. */
@@ -436,38 +532,60 @@
 
     segment_get(&files->out_seg, (void *)files->out_val, Ri[0][0], Ri[0][1]);
     files->out_val[1] = 0;	/*candidate pixel flag, only one merge allowed per t iteration */
+    /* if separate out candidate flag, can do all changes with helper function...otherwise remember: */
 
 
+    G_debug(1, "\t\tMerging, segment number: %d, including pixels:",
+	    files->out_val[0]);
+
     /* for each member of Ri and Rk, write new average bands values and segment values */
     for (n = 0; n < Ri_count; n++) {
 	segment_put(&files->bands_seg, (void *)files->bands_val, Ri[n][0],
 		    Ri[n][1]);
 	segment_put(&files->out_seg, (void *)files->out_val, Ri[n][0],
 		    Ri[n][1]);
+	files->candidate_count--;
+	G_debug(1, "line 508, \t\t\t\tcc = %d", files->candidate_count);
+	G_debug(1, "\t\tRi row: %d, col: %d", Ri[n][0], Ri[n][1]);
     }
     for (n = 0; n < Rk_count; n++) {
 	segment_put(&files->bands_seg, (void *)files->bands_val, Rk[n][0],
 		    Rk[n][1]);
 	segment_put(&files->out_seg, (void *)files->out_val, Rk[n][0],
 		    Rk[n][1]);
+	files->candidate_count--;
+	G_debug(1, "line 516, \t\t\t\tcc = %d", files->candidate_count);
+	G_debug(1, "\t\tRk row: %d, col: %d", Rk[n][0], Rk[n][1]);
+
     }
 
+    files->candidate_count++;	/* had already counted down the starting pixel Ri[0] at the beginning... */
+    G_debug(1, "line 522, \t\t\t\tcc = %d", files->candidate_count);
     return 0;
 }
 
 /* TODO.. helper function, maybe make more general? */
-int set_candidate_flag(int Ri[100][2], int value, struct files *files)
+int set_candidate_flag(int Ri[100][2], int count, int value,
+		       struct files *files)
 {
     /* Ri is list of pixels, value is new value of flag */
     int n;
 
     /* TODO: Ri data structure... eventually just need to process all pixels in Ri. */
-    for (n = 0; n < 100; n++) {
+    for (n = 0; n <= count; n++) {
 	segment_get(&files->out_seg, (void *)files->out_val, Ri[n][0], Ri[n][1]);	/* this may change... */
 	files->out_val[1] = value;	/*candidate pixel flag */
 	segment_put(&files->out_seg, (void *)files->out_val, Ri[n][0],
 		    Ri[n][1]);
 
+	/* also increment how many pixels remain to be processed */
+
+	if (value == 0)
+	    files->candidate_count--;
+	else if (value == 1)
+	    files->candidate_count++;
+	G_debug(1, "line 544, \t\t\t\tcc = %d", files->candidate_count);
+
     }
     return 0;
 }

Modified: grass-addons/grass7/imagery/i.segment/iseg.h
===================================================================
--- grass-addons/grass7/imagery/i.segment/iseg.h	2012-06-12 21:45:12 UTC (rev 52052)
+++ grass-addons/grass7/imagery/i.segment/iseg.h	2012-06-12 23:03:03 UTC (rev 52053)
@@ -24,14 +24,14 @@
 
     /* files */
     int nbands;
+    int candidate_count;	/*how many candidate pixels remain */
     SEGMENT bands_seg, out_seg;	/* bands is for input, normal application is landsat bands, but other input can be included in the group. */
     double *bands_val;		/* array, to hold all input values at one pixel */
     double *second_val;		/* to hold values at second point for similarity comparison */
     int *out_val;		/* array, to hold the segment ID and processing flag(s) */
     char *out_name;		/* name of output raster map */
 
-    /*int **no_check; *//* TODO maybe as SEGMENT.  Also can this be smaller then an int?  Just need to save 0 and 1. */
-    int no_check[100][2];
+    SEGMENT no_check;		/* pixels that have already been checked during this neighbor finding routine */
 
     /* RASTER_MAP_TYPE data_type;       Removed: input is always DCELL, output is CELL. 
      *  TODO: if input might be smaller then DCELL, we could detect size and allocate accordingly. */
@@ -56,25 +56,27 @@
 
 };
 
-
-/* I think if I use function pointers, I can set up one time in the input
- * what similarity function, etc, will be used later in the processing
- * and make it easier to add additional variations later.
- */
-
 struct functions
 {
     int method;			/* Segmentation method */
-    int (*find_pixel_neighbors) (int[2], int[8][2], struct files *);	/*pixel, pixel_neighbors */
-    double (*calculate_similarity) (int[2], int[2], struct files *,
+
+    /* Some function pointers to set one time in parse_args() */
+    int (*find_pixel_neighbors) (int, int, int[8][2], struct files *);	/*parameters: row, col, pixel_neighbors */
+    double (*calculate_similarity) (int[2], int[2], struct files *,	/*parameters: two points (row,col) to compare */
 				    struct functions *);
 
-    int num_pn;			/* number of pixel neighbors  int, 4 or 8. */
-
+    int num_pn;			/* number of pixel neighbors  int, 4 or 8. TODO: can remove if pixel neighbors is list instead of array.  But maybe this one is small enough that is faster as array? */
     float threshold;		/* similarity threshold */
 
 };
 
+struct pixel
+{
+    int row;
+    int col;
+    struct pixel *next;
+};
+
 /* parse_args.c */
 /* gets input from user, validates, and sets up functions */
 int parse_args(int, char *[], struct files *, struct functions *);
@@ -86,15 +88,15 @@
 int create_isegs(struct files *, struct functions *);
 int io_debug(struct files *, struct functions *);
 int region_growing(struct files *, struct functions *);
-int find_segment_neighbors(int[][2], int[][2], int, int, struct files *, struct functions *);	/* TODO: need data structure for Ri, Rin */
-int set_candidate_flag(int[100][2], int, struct files *);
+int find_segment_neighbors(int[][2], int[][2], int *, int *, struct files *, struct functions *);	/* TODO: need data structure for Ri, Rin */
+int set_candidate_flag(int[100][2], int, int, struct files *);
 int merge_values(int[100][2], int[100][2], int, int, struct files *);	/* I assume this is a weighted mean? */
-int find_four_pixel_neighbors(int[2], int[][2], struct files *);
-int find_eight_pixel_neighbors(int[2], int[8][2], struct files *);
+int find_four_pixel_neighbors(int, int, int[][2], struct files *);
+int find_eight_pixel_neighbors(int, int, int[8][2], struct files *);
 double calculate_euclidean_similarity(int[2], int[2], struct files *,
 				      struct functions *);
 
 
 /* write_output.c */
-/* also currently closes files */
 int write_output(struct files *);
+int close_files(struct files *);

Modified: grass-addons/grass7/imagery/i.segment/main.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/main.c	2012-06-12 21:45:12 UTC (rev 52052)
+++ grass-addons/grass7/imagery/i.segment/main.c	2012-06-12 23:03:03 UTC (rev 52053)
@@ -38,20 +38,28 @@
 	_("Outputs a single segmention map (raster) based on input values in an image group.");
 
     if (parse_args(argc, argv, &files, &functions) != 0)
-	G_fatal_error("Error in parse_args()");
+	G_debug(1, "Error in parse_args()");	/* TODO: should these be debug or G_fatal_error() or nested if statement? want to clean up mem and temp files */
 
     G_debug(1, "Main: starting open_files()");
     if (open_files(&files) != 0)
-	G_fatal_error("Error in open_files()");
+	G_debug(1, "Error in open_files()");
 
     G_debug(1, "Main: starting create_isegs()");
     if (create_isegs(&files, &functions) != 0)
-	G_fatal_error("Error in create_isegs()");
+	G_debug(1, "Error in create_isegs()");
 
     G_debug(1, "Main: starting write_output()");
     if (write_output(&files) != 0)
-	G_fatal_error("Error in write_output()");
+	G_debug(1, "Error in write_output()");
 
+    G_debug(1, "Main: starting close_files()");
+    close_files(&files);
+
+    /* TODO - G_fatal_error() called in sub routines - do I need to run close_files() before quitting?
+     * http://rackerhacker.com/2010/03/18/sigterm-vs-sigkill/
+     * "Standard C applications have a header file that contains the steps that the process should follow if it receives a particular signal. "
+     *  */
+
     G_done_msg("Number of segments created: ");
 
     exit(EXIT_SUCCESS);

Added: grass-addons/grass7/imagery/i.segment/open_files.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/open_files.c	                        (rev 0)
+++ grass-addons/grass7/imagery/i.segment/open_files.c	2012-06-12 23:03:03 UTC (rev 52053)
@@ -0,0 +1,140 @@
+/* PURPOSE:      opening input rasters and creating segmentation files */
+
+#include <stdlib.h>
+#include <grass/gis.h>
+#include <grass/glocale.h>
+#include <grass/imagery.h>
+#include <grass/segment.h>	/* segmentation library */
+#include "iseg.h"
+
+int open_files(struct files *files)
+{
+    struct Ref Ref;		/* group reference list */
+    int *in_fd;
+    int n, row, col, srows, scols, inlen, outlen, nseg;
+    DCELL **inbuf;		/* buffer array, to store lines from each of the imagery group rasters */
+
+
+    G_debug(1, "Checking image group...");
+    /* references: i.cost r.watershed/seg and http://grass.osgeo.org/programming7/segmentlib.html */
+
+    /* ****** open the input rasters ******* */
+
+    /* TODO, this is from i.smap/openfiles.c  lines 17-23 checked if subgroup had maps, does API handles the checks? */
+
+    if (!I_get_group_ref(files->image_group, &Ref))
+	G_fatal_error(_("Unable to read REF file for group <%s>"),
+		      files->image_group);
+
+    if (Ref.nfiles <= 0)
+	G_fatal_error(_("Group <%s> contains no raster maps"),
+		      files->image_group);
+
+    /* Read Imagery Group */
+
+    in_fd = G_malloc(Ref.nfiles * sizeof(int));
+    inbuf = (DCELL **) G_malloc(Ref.nfiles * sizeof(DCELL *));
+
+    G_debug(1, "Opening input rasters...");
+    for (n = 0; n < Ref.nfiles; n++) {
+	inbuf[n] = Rast_allocate_d_buf();
+	in_fd[n] = Rast_open_old(Ref.file[n].name, Ref.file[n].mapset);
+    }
+
+
+    /* ********** find out file segmentation size ************ */
+    G_debug(1, "Calculate temp file sizes...");
+
+    files->nbands = Ref.nfiles;
+
+    /* size of each element to be stored */
+
+    inlen = sizeof(double) * Ref.nfiles;
+    outlen = sizeof(int) * 2;	/* change in write_output.c if this value changes TODO: better to save this in the files data structure? */
+
+    /*TODO: i.cost and i.watershed take different approaches...hardcode for now */
+    /* when fine tuning, should be a power of 2 and not larger than 256 for speed reasons */
+    srows = 64;
+    scols = 64;
+
+    /* TODO: make calculations for this */
+    nseg = 8;
+
+
+    /* ******* create temporary segmentation files ********* */
+    G_debug(1, "Getting temporary file names...");
+    /* Initalize access to database and create temporary files */
+
+    G_debug(1, "Image size:  %d rows, %d cols", files->nrows, files->ncols);
+    G_debug(1, "Segmented to tiles with size:  %d rows, %d cols", srows,
+	    scols);
+    G_debug(1, "Data element size, in: %d , out: %d ", inlen, outlen);
+    G_debug(1, "number of segments to have in memory: %d", nseg);
+
+    /* size: reading all input bands as DCELL  TODO: could consider checking input to see if it is all FCELL or CELL, could reduce memory requirements. */
+
+    if (segment_open
+	(&files->bands_seg, G_tempfile(), files->nrows, files->ncols, srows,
+	 scols, inlen, nseg) != 1)
+	G_fatal_error("Unable to create input temporary files");
+
+    G_debug(1, "finished segment_open(...bands_seg...)");
+
+    /* TODO: signed integer gives a 2 billion segment limit, depending on how the initialization is done, this means 2 billion max input pixels. */
+    if (segment_open
+	(&files->out_seg, G_tempfile(), files->nrows, files->ncols, srows,
+	 scols, outlen, nseg) != 1)
+	G_fatal_error("Unable to create output temporary files");
+
+    if (segment_open(&files->no_check, G_tempfile(), files->nrows, files->ncols, srows, scols, sizeof(int), nseg) != 1)	/* todo could make this smaller ? just need 0 or 1 */
+	G_fatal_error("Unable to create flag temporary files");
+
+    /* load input bands to segment structure */
+    G_debug(1, "Reading input rasters into segmentation data files...");
+
+    files->bands_val = (double *)G_malloc(inlen);
+    files->second_val = (double *)G_malloc(inlen);
+
+    for (row = 0; row < files->nrows; row++) {
+	for (n = 0; n < Ref.nfiles; n++) {
+	    Rast_get_d_row(in_fd[n], inbuf[n], row);
+	}
+	for (col = 0; col < files->ncols; col++) {
+	    for (n = 0; n < Ref.nfiles; n++) {
+		files->bands_val[n] = inbuf[n][col];
+	    }
+	    segment_put(&files->bands_seg, (void *)files->bands_val, row,
+			col);
+	}
+    }
+
+    /* Initialize output segmentation file */
+
+    G_debug(1, "G_malloc size: = <%d>", (int)(2 * sizeof(int)));
+    files->out_val = (int *)G_malloc(2 * sizeof(int));
+
+    n = 1;
+    for (row = 0; row < files->nrows; row++) {
+	for (col = 0; col < files->ncols; col++) {
+	    files->out_val[0] = n;	/*starting segment number TODO: for seeds this will be different */
+	    files->out_val[1] = 0;	/*flag */
+	    segment_put(&files->out_seg, (void *)files->out_val, row, col);
+	    n++;		/* sequentially number all pixels with their own segment ID */
+	}
+    }
+
+    files->candidate_count = 0;	/* counter for remaining candidate pixels */
+
+    /* Free memory */
+
+    for (n = 0; n < Ref.nfiles; n++) {
+	Rast_close(in_fd[n]);
+    }
+
+    G_free(inbuf);
+    G_free(in_fd);
+
+    /* Need to clean up anything else? */
+
+    return 0;
+}

Modified: grass-addons/grass7/imagery/i.segment/parse_args.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/parse_args.c	2012-06-12 21:45:12 UTC (rev 52052)
+++ grass-addons/grass7/imagery/i.segment/parse_args.c	2012-06-12 23:03:03 UTC (rev 52053)
@@ -84,17 +84,13 @@
 
     files->image_group = group->answer;
 
-    /* TODO: I'm assuming it is already validated as a number.  Is this OK, or is there a better way to cast the input? */
-    /* reference r.cost line 313 
-       if (sscanf(opt5->answer, "%d", &maxcost) != 1 || maxcost < 0)
-       G_fatal_error(_("Inappropriate maximum cost: %d"), maxcost); */
-
     if (G_legal_filename(output->answer) == 1)
 	files->out_name = output->answer;	/* name of output raster map */
     else
 	G_fatal_error("Invalid output raster name.");
 
     /* segmentation methods:  0 = debug, 1 = region growing */
+    /* TODO, instead of string compare, does the Option structure have these already numbered? */
 
     if (strncmp(method->answer, "io_debug", 5) == 0)
 	functions->method = 0;
@@ -105,7 +101,10 @@
 
     G_debug(1, "segmentation method: %d", functions->method);
 
-
+    /* TODO: I'm assuming threshold is already validated as a number.  Is this OK, or is there a better way to cast the input? */
+    /* reference r.cost line 313 
+       if (sscanf(opt5->answer, "%d", &maxcost) != 1 || maxcost < 0)
+       G_fatal_error(_("Inappropriate maximum cost: %d"), maxcost); */
     sscanf(threshold->answer, "%f", &functions->threshold);
 
     if (diagonal->answer == 0) {
@@ -119,9 +118,6 @@
 	G_debug(1, "eight (3x3) pixel neighborhood");
     }
 
-    /* note from tutorial: You may have got to use the complete name of the member function 
-     * including class-name and scope-operator (::).) */
-
     /* TODO add user input for this */
     functions->calculate_similarity = &calculate_euclidean_similarity;
 

Modified: grass-addons/grass7/imagery/i.segment/write_output.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/write_output.c	2012-06-12 21:45:12 UTC (rev 52052)
+++ grass-addons/grass7/imagery/i.segment/write_output.c	2012-06-12 23:03:03 UTC (rev 52053)
@@ -1,5 +1,5 @@
 /* transfer the segmented regions from the segmented data file to a raster file */
-/* put closing segment files here for now, OK to combine or better to put in a seperate function? */
+/* close_files() function is at bottom */
 
 #include <stdlib.h>
 #include <grass/gis.h>
@@ -36,17 +36,26 @@
 	Rast_put_row(out_fd, outbuf, CELL_TYPE);
     }
 
+    /* close and save file */
+    Rast_close(out_fd);
 
+    return 0;
+}
+
+int close_files(struct files *files)
+{
     /* close segmentation files and output raster */
     G_debug(1, "closing files");
     segment_close(&files->bands_seg);
     segment_close(&files->out_seg);
-    Rast_close(out_fd);
+    segment_close(&files->no_check);
 
-    for (n = 0; n < files->nrows; n++)
-	G_free(files->no_check[n]);
-    G_free(files->no_check);
+    /* close segmentation files and output raster */
 
+    G_free(files->bands_val);
+    G_free(files->second_val);
+    G_free(files->out_val);
+
     /* anything else left to clean up? */
 
     return 0;



More information about the grass-commit mailing list