    /**********************************************
    *
    *  grow(...
    *
    *  This function is an object detector.
    *  Its input is an binary image array 
    *  containing 0's and value's.
    *  It searches through the image and connects
    *  the adjacent values.
    *
    ***********************************************/

grow(binary, value)
   short binary[ROWS][COLS],
         value;
{
   char name[80];

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

   short g_label, stack[STACK_SIZE][2];

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

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

   for(i=0; i<ROWS; i++){
      for(j=0; j<COLS; j++){
         stack_file_in_use =  0;
         stack_empty       =  1;
         pointer           = -1;

               /**********************************
               *
               *  Search for the first pixel of
               *  a region.
               *
               ***********************************/

         if(binary[i][j] == value){
            label_and_check_neighbor(binary, stack, g_label,
                           &stack_empty, &pointer, i, j,
                           value, &stack_file_in_use,
                           &first_call);
            object_found = 1;
         }  /* ends if binary[i]j] == value */

               /*****************************
               *
               *  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  */

            label_and_check_neighbor(binary,
                        stack, g_label,
                        &stack_empty,
                        &pointer, pop_i,
                        pop_j, value,
                        &stack_file_in_use,
                        &first_call);
         }  /* ends while stack_empty == 0 */

         if(object_found == 1){
            object_found = 0;
            ++g_label;
         }  /* ends if object_found == 1 */

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

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

} /* ends grow  */

   /********************************************
   *
   *  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.
   *
   ***********************************************/

label_and_check_neighbor(binary_image, stack,
                         g_label, stack_empty,
                         pointer, r, e, value,
                         stack_file_in_use,
                         first_call)
int   e,
      *first_call,
      *pointer,
      r,
      *stack_empty,
      *stack_file_in_use;

short binary_image[ROWS][COLS],
      g_label,
      stack[STACK_SIZE][2],
      value;
{
   int already_labeled = 0,
       i, j;

   if (binary_image[r][e] == g_label)
      already_labeled = 1;

   binary_image[r][e] = g_label;

      /***************************************
      *
      *   Look at the 8 neighors of the
      *   point r,e.
      *
      *   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(binary_image[i][j] == value){
               *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*/

            }  /* end of if binary_image == value */
         }  /* end if i and j are on the image */
      }  /* ends loop over i rows           */
   }  /* ends loop over j columns        */
}  /* ends label_and_check_neighbors  */

   /****************************************
   *
   *   push_data_onto_stack_file(...
   *
   *   This function takes the stack array
   *   and pushes it onto the stack file.
   *
   *****************************************/

push_data_onto_stack_file(stack, pointer, first_call)
   int   *first_call, *pointer;
   short stack[STACK_SIZE][2];
{
   char  backup_file_name[MAX_NAME_LENGTH];
   FILE  *backup_file_pointer, *stack_file_pointer;
   int   diff, i;
   short holder[STACK_FILE_LENGTH][2];

   printf("\nSFO> Start of push_data_onto_stack ");

   diff = STACK_SIZE - STACK_FILE_LENGTH;

       /*******************************************
       *
       *   Copy the elements to be stored to the
       *   stack file into holder
       *
       ********************************************/

   for(i=0; i<STACK_FILE_LENGTH; i++){
      holder[i][0] = stack[i][0];
      holder[i][1] = stack[i][1];
   }
       /*******************************************
       *
       *   Move the elements of the stack down
       *
       *******************************************/

   for(i=0; i<diff; i++){
      stack[i][0] = stack[i + STACK_FILE_LENGTH][0];
      stack[i][1] = stack[i + STACK_FILE_LENGTH][1];
   }

       /*******************************************
       *
       *   Fill the top of the stack with zeros
       *
       *******************************************/

   for(i=diff; i<STACK_SIZE; i++){
      stack[i][0] = 0;
      stack[i][1] = 0;
   }

   *pointer = *pointer - STACK_FILE_LENGTH;

       /************************************************
       *
       *   Store the holder array into the stack file.
       *   Open the stack file for writing in binary
       *   mode. If the file does not exist it will be
       *   created. If the file does exist it will be
       *   over written.
       *
       *   PUSH - IF first_time == 1 then write to stack
       *          ELSE write to stack.bak
       *          append stack onto stack.bak
       *          copy stack.bak to stack
       *          this has the effect of writing
       *          to the beginning of the stack.
       *
       ************************************************/

   if(*first_call == 1){

      *first_call = *first_call + 1;
      if((stack_file_pointer = fopen(STACK_FILE,"wb"))
                                     == NULL)
         printf("\nSFO> Could not open stack file");
      else{
         /*printf("\n\nSFO> Writing to stack file");*/
         fwrite(holder, sizeof(holder),
                1, stack_file_pointer);
         fclose(stack_file_pointer);
      }  /*  ends else could not open stack_file  */

   }  /*  ends if *first_call == 1  */
   else{  /* else stack file has been used already  */
      strcpy(backup_file_name, STACK_FILE);
      append_string(".bak\0", backup_file_name);
      if((backup_file_pointer =
          fopen(backup_file_name, "wb")) == NULL)
         printf("\nSFO> Could not open backup file");
      else{
         /*printf("\n\nSFO> Writing to backup file");*/
         fwrite(holder, sizeof(holder),
                1, backup_file_pointer);
         fclose(backup_file_pointer);
      }  /*  ends else could not open backup_file  */

      append_stack_files(backup_file_name,
                         STACK_FILE, holder);
      copy_stack_files(backup_file_name,
                       STACK_FILE, holder);

   }  /*  ends else first_call != 1  */

   printf("--- End of push_data_onto_stack");

}  /* ends push_data_onto_stack_file  */

   /****************************************
   *
   *   pop_data_off_of_stack_file(...
   *
   *   This function pops the stack array
   *   off of the stack file.
   *
   *****************************************/

pop_data_off_of_stack_file(stack, pointer,
                           stack_file_in_use)
   int   *pointer, *stack_file_in_use;
   short stack[STACK_SIZE][2];
{
   char  backup_file_name[MAX_NAME_LENGTH];
   FILE  *backup_file_pointer, *stack_file_pointer;
   int   i;
   long  write_counter;
   short holder[STACK_FILE_LENGTH][2],
         holder2[STACK_FILE_LENGTH][2];

       /*******************************************
       *
       *   POP - Read 1 time from stack
       *         Copy the remainder of stack to
       *            stack.bak
       *         Copy stack.bak to stack
       *         This has the effect of popping off
       *         of the stack.
       *
       *   Read the holder array from the stack file.
       *   Open the stack file for reading in binary
       *   mode.
       *
       *   If it requires more than one write to
       *   copy the remainder of stack to
       *   stack.bak then there is still data in the
       *   stack file so set stack_file_in_use = 1.
       *   Else set it to 0.
       *
       **********************************************/

   printf("\nSFO> Start of pop_data_off_of_stack ");
   write_counter = 0;

   strcpy(backup_file_name, STACK_FILE);
   append_string(".bak\0", backup_file_name);

   if( (stack_file_pointer =
          fopen(STACK_FILE, "rb")) == NULL)
      printf("\nSFO> Could not open stack file");
   else{
      /*printf("\n\nSFO> Reading from stack file");*/
      fread(holder, sizeof(holder),
            1, stack_file_pointer);
      backup_file_pointer =
            fopen(backup_file_name, "wb");
      while( fread(holder2, sizeof(holder2),
                   1, stack_file_pointer) ){
         fwrite(holder2, sizeof(holder2),
                1, backup_file_pointer);
         ++write_counter;
      }  /* ends while reading  */
      if(write_counter > 0)
         *stack_file_in_use = 1;
      else
         *stack_file_in_use = 0;

      fclose(backup_file_pointer);
      fclose(stack_file_pointer);
   }  /* ends else could not open stack file  */

   copy_stack_files(backup_file_name,
                    STACK_FILE, holder2);

   for(i=0; i<STACK_FILE_LENGTH; i++){
      stack[i][0] = holder[i][0];
      stack[i][1] = holder[i][1];
   }

   *pointer = *pointer + STACK_FILE_LENGTH - 1;

   printf("--- End of pop_data_off_of_stack");
}  /* ends pop_data_off_of_stack_file  */

   /*********************************************
   *
   *   append_stack_files(...
   *
   *   Append the second file onto the end
   *   of the first.
   *
   ***********************************************/

append_stack_files(first_file, second_file, holder)
   char first_file[], second_file[];
   short holder[STACK_FILE_LENGTH][2];
{
   FILE  *first, *second;
   int   i;

   if((first = fopen(first_file, "r+b")) == NULL)
      printf("\n\nSFO> Cannot open file %s",
             first_file);

   if((second = fopen(second_file, "rb")) == NULL)
      printf("\n\nSFO> Cannot open file %s",
             second_file);

          /*****************************************
          *
          *  Seek to the end of the first file and
          *  to the beginning of the second file.
          *
          *******************************************/

   fseek(first, 0L, 2);
   fseek(second, 0L, 0);

   while(fread(holder, sizeof(holder), 1, second) ){
      fwrite(holder, sizeof(holder), 1, first);
   }  /* ends while reading  */

   fclose(first);
   fclose(second);

}  /*  ends append_stack_files  */

   /********************************************
   *
   *   copy_stack_files(...
   *
   *   Copy the first file to the second.
   *
   **********************************************/

copy_stack_files(first_file, second_file, holder)
   char first_file[], second_file[];
   short holder[STACK_FILE_LENGTH][2];
{
   FILE  *first, *second;
   int   i;

   if( (first = fopen(first_file, "rb")) == NULL)
      printf("\n\nSFO> Cannot open file %s",
             first_file);

   if( (second = fopen(second_file, "wb")) == NULL)
      printf("\n\nSFO> Cannot open file %s",
             second_file);

          /******************************************
          *
          *  Seek to the beginning of the first file.
          *
          *******************************************/

   fseek(first, 0L, 0);

   while( fread(holder, sizeof(holder), 1, first) ){
      fwrite(holder, sizeof(holder), 1, second);
   }  /* ends while reading  */

   fclose(first);
   fclose(second);

}  /*  ends copy_stack_files */

