    /**********************************************
    *
    *   pixel_grow(...
    *
    *   The function grows regions.  It is similar
    *   to the grow function in segment.c, but it
    *   has several new capabilities.  It can
    *   eliminate regions if they are too large or
    *   too small.
    *
    *   It ignores pixels = FORGET_IT.  This allows
    *   it to ignore edges or regions already
    *   eliminated from consideration.
    *
    *   It adds pixels to a growing region only if
    *   the pixel is close enough to the average gray
    *   level of that region.
    *
    ***********************************************/

pixel_grow(input, output, diff, min_area, max_area)
   short input[ROWS][COLS],
         output[ROWS][COLS],
         max_area,
         min_area,
         diff;
{
   char name[80];

   int count,
       first_call,
       i,
       ii,
       j,
       jj,
       object_found,
       pointer,
       pop_i,
       pop_j,
       stack_empty,
       stack_file_in_use;

   short g_label, target, sum, stack[STACK_SIZE][2];

   for(i=0; i<ROWS; i++)
      for(j=0; j<COLS; j++)
         output[i][j] = 0;

   g_label       = 2;
   object_found  = 0;
   first_call    = 1;

            /*************************************
            *
            *   Now begin the process of growing
            *   regions.
            *
            **************************************/

   for(i=0; i<ROWS; i++){
if( (i%4) == 0) printf("\n");
printf("-i=%3d label=%3d", i, g_label);
      for(j=0; j<COLS; j++){

         target            = input[i][j];
         sum               = target;
         count             = 0;
         stack_file_in_use = 0;
         stack_empty       = 1;
         pointer           = -1;

               /**********************************
               *
               *  Search for the first pixel of
               *  a region.  It must not equal
               *  FORGET_IT, and it must be close
               *  enough to the target (ave value).
               *
               ***********************************/

         if(input[i][j] != FORGET_IT            &&
            is_close(input[i][j], target, diff) &&
            output[i][j] == 0){
            pixel_label_and_check_neighbor(input,
                           output, &target, &sum,
                           &count, stack, g_label,
                           &stack_empty, &pointer,
                           i, j, diff,
                           &stack_file_in_use,
                           &first_call);
            object_found = 1;
         }  /* ends if is_close */
               /*****************************
               *
               *  If the stack is not empty,
               *  pop the coordinates of
               *  the pixel off the stack
               *  and check its 8 neighbors.
               *
               *******************************/

         while(stack_empty == 0){
            pop_i = stack[pointer][0]; /* POP       */
            pop_j = stack[pointer][1]; /* OPERATION */
            --pointer;
            if(pointer <= 0){
               if(stack_file_in_use){
                  pop_data_off_of_stack_file(
                                 stack,
                                 &pointer,
                                 &stack_file_in_use);
               }  /* ends if stack_file_in_use  */
               else{
                  pointer     = 0;
                  stack_empty = 1;
               }  /* ends else stack file is
                     not in use  */
            }  /*  ends if point <= 0  */
            pixel_label_and_check_neighbor(input,
                           output, &target, &sum,
                           &count, stack, g_label,
                           &stack_empty, &pointer,
                           pop_i, pop_j,
                           diff, &stack_file_in_use,
                           &first_call);
         }  /* ends while stack_empty == 0 */

         if(object_found == 1){
            object_found = 0;

                  /**********************************
                  *
                  *  The object must be in the
                  *  size constraints given by
                  *  min_area and max_area
                  *
                  *********************************/

            if(count >= min_area  &&
               count <= max_area)
               ++g_label;
                  /**********************************
                  *
                  *   Remove the object from the
                  *   output.  Set all pixels in the
                  *   object you are removing to
                  *   FORGET_IT.
                  *
                  **********************************/

            else{
               for(ii=0; ii<ROWS; ii++){
                  for(jj=0; jj<COLS; jj++){
                     if(output[ii][jj] == g_label){
                        output[ii][jj] = 0;
                        input[ii][jj]  = FORGET_IT;
                     }  /* ends if output == g_label */
                  }  /* ends loop over jj */
               }  /* ends loop over ii */
            }  /* ends else remove object */
         }  /* ends if object_found == 1 */

      }   /* ends loop over j */
   }  /* ends loop over i */

   printf("\nGROW> found %d objects", g_label);

} /* ends pixel_grow  */





   /********************************************
   *
   *  pixel_label_and_check_neighbors(...
   *
   *  This function labels a pixel with an object
   *  label and then checks the pixel's 8
   *  neighbors.  If any of the neigbors are
   *  set, then they are also labeled.
   *
   *  It also updates the target or ave pixel
   *  value of the pixels in the region being
   *  grown.
   *
   ***********************************************/

pixel_label_and_check_neighbor(input_image,
                         output_image, target,
                         sum, count, stack,
                         g_label, stack_empty,
                         pointer, r, e, diff,
                         stack_file_in_use,
                         first_call)
int   *count,
      e,
      *first_call,
      *pointer,
      r,
      *stack_empty,
      *stack_file_in_use;

short input_image[ROWS][COLS],
      output_image[ROWS][COLS],
      g_label,
      *sum,
      *target,
      stack[STACK_SIZE][2],
      diff;
{
   int already_labeled = 0,
       i, j;

   if (output_image[r][e] != 0)
      already_labeled = 1;

   output_image[r][e] = g_label;
   *count  = *count + 1;
   if(*count > 1){
      *sum    = *sum + input_image[r][e];
      *target = *sum / *count;
   }

      /***************************************
      *
      *   Look at the 8 neighors of the
      *   point r,e.
      *
      *   Ensure the points are close enough
      *   to the target and do not equal
      *   FORGET_IT.
      *
      *   Ensure the points you are checking
      *   are in the image, i.e. not less
      *   than zero and not greater than
      *   ROWS-1 or COLS-1.
      *
      ***************************************/

   for(i=(r-1); i<=(r+1); i++){
      for(j=(e-1); j<=(e+1); j++){

         if((i>=0)   &&
            (i<=ROWS-1)  &&
            (j>=0)   &&
            (j<=COLS-1)){

            if( input_image[i][j] != FORGET_IT   &&
                is_close(input_image[i][j],
                            *target, diff)       &&
                output_image[i][j] == 0){
               *pointer           = *pointer + 1;
               stack[*pointer][0] = i; /* PUSH      */
               stack[*pointer][1] = j; /* OPERATION */
               *stack_empty       = 0;

               if(*pointer >= (STACK_SIZE -
                               STACK_FILE_LENGTH)){
                  push_data_onto_stack_file(stack,
                            pointer, first_call);
                  *stack_file_in_use = 1;
               }  /* ends if *pointer >=
                     STACK_SIZE - STACK_FILE_LENGTH*/

            }  /* ends if is_close */
         }  /* end if i and j are on the image */
      }  /* ends loop over i rows           */
   }  /* ends loop over j columns        */
}  /* ends pixel_label_and_check_neighbors  */



   /********************************************
   *
   *  is_close(...
   *
   *  This function tests to see if two pixel
   *  values are close enough together.  It
   *  uses the delta parameter to make this
   *  judgement.
   *
   ***********************************************/

is_close(a, b, delta)
   short a, b, delta;
{
   int   result = 0;
   short diff;

   diff = a-b;
   if(diff < 0) diff = diff*(-1);
   if(diff < delta)
      result = 1;
   return(result);
}  /* ends is_close */

