 /*
  * Khoros: $Id: vlabel.c,v 1.1 1991/05/10 15:46:10 khoros Exp $
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id: vlabel.c,v 1.1 1991/05/10 15:46:10 khoros Exp $";
#endif

 /*
  * $Log: vlabel.c,v $
 * Revision 1.1  1991/05/10  15:46:10  khoros
 * Initial revision
 *
  */ 

/*
 *----------------------------------------------------------------------
 *
 * Copyright 1991, University of New Mexico.  All rights reserved.
 * Permission to copy and modify this software and its documen-
 * tation only for internal use in your organization is hereby
 * granted, provided that this notice is retained thereon and
 * on all copies.  UNM makes no representations as too the sui-
 * tability and operability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 * 
 * UNM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
 * NESS.  IN NO EVENT SHALL UNM BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY OTHER DAMAGES WHAT-
 * SOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PER-
 * FORMANCE OF THIS SOFTWARE.
 * 
 * No other rights, including for example, the right to redis-
 * tribute this software and its documentation or the right to
 * prepare derivative works, are granted unless specifically
 * provided in a separate license agreement.
 *---------------------------------------------------------------------
 */

#include "unmcopyright.h"        /* Copyright 1991 by UNM */

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 >>>>
 >>>>         File Name: vlabel.c
 >>>>
 >>>>      Program Name: vlabel
 >>>>
 >>>>      Program Desc: 
 >>>>	
 >>>>	Performs a Labeling on Multiband or Cluster Images
 >>>>	
 >>>>	
 >>>>            Author: Pascal ADAM
 >>>>
 >>>> Date Last Updated: Tue Mar  5 22:20:57 1991
 >>>>
 >>>>          Routines: main- the main program for vlabel
 >>>> 		 gw_usage - gives usage of the program
 >>>> 		 gw_args  - gets arguments of program from command line
 >>>>
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/


#include "vlabel.h"


/****************************************************************
 *
 * Routine Name:  main program for vlabel
 *
 *       Input:  
 *        -o  output image after the labelling process 
 *        -merge  if flag= 1 the small regions will be merged together in connex regions, or will be included to existing labelled regions 
 *        -m  1 for euclidean distance, 2 for city block
 *		1 (Use the Euclidean Distance),
 *		or 2 (Use the City block Distance)
 *		 
 *        -c  1 for the 4 connectivity, 2 for 8 connectivity
 *		1 (if Yes use the 4 Connectivity),
 *		or 2 (if Yes use the 8 Connectivity)
 *		 
 *
 *        -i1  input image    -OR-
 *        -i2  input image for cluster centers
 *        -n  Number of region that the user wishes to get from the labelling process   (2 < value < 2500)   -OR-
 *        -f  the higher the factor the finer the regions  (0.000 < value < 1.000)
 *
 *        [-i3] input image for cluster numbers
 *        [-asc] output file for vlabel result display
 *        [-w] specifies the border width in pixels (default = 0)  (0 < value < 16)
 *        [-s] Minimum number of pixel to keep in label region  (0.000 < value < 100.000)
 *
 *
 *
 ****************************************************************/


main(argc, argv)
int argc;
char *argv[];
{

/* -main_variable_list */
struct xvimage *image, 
               *clus_numb, 
               *clus_cent, 
               *label, 
               *readimage(),
               *createimage();

int dist, 
    nc, 
    nr, 
    connect, 
    cas,
    opt_auto, 
    merge,
    region_number;

FILE *printdev;
char *dummy = '\0';

/* -main_variable_list_end */

	program = VStrcpy(argv[0]);
	ac = argc;
	av = argv;

	khoros_init();

	gw_get_args();

/* -main_before_lib_call */
if (vlabel->i1_flag == TRUE)  {
   image = readimage(vlabel->i1_file);
   if (image == NULL) {
      (void) fprintf(stderr,"vlabel: image could not be read\n\n");
      exit(1);
      }
   (void) proper_num_images(program,image,1,TRUE);
   (void) proper_map_enable(program,image,VFF_MAP_OPTIONAL,TRUE);

   if (lvconvert(image,VFF_TYP_FLOAT,0,1,0.0,1.0) == 0 ) {
      (void) fprintf(stderr,"vlabel: lvconvert failure\n\n");
      exit(1);
      }
   nc = image->row_size;
   nr = image->col_size;

   if ( (vlabel->w_int > (nc/2)) ||
        (vlabel->w_int > (nr/2))   ) {
      (void) fprintf(stderr,
      "vlabel:border too large for the image size \n\n");
      exit(1);
      }
   }
if (vlabel->i2_flag == TRUE)  {
   clus_cent = readimage(vlabel->i2_file);
   if (clus_cent == NULL) {
      (void) fprintf(stderr,"vlabel: cluster center image could not be read\n\n");
      exit(1);
      }
   (void) proper_num_images(program,clus_cent,1,TRUE);
   (void) proper_map_enable(program,clus_cent,VFF_MAP_OPTIONAL,TRUE);

   if (clus_cent ->data_storage_type != VFF_TYP_4_BYTE) {
      (void) fprintf(stderr,
      "vlabel: cluster center image has to be a FLOAT image\n\n");
      exit(1);
      }

   }

if (vlabel->i3_flag == TRUE)  {
   clus_numb = readimage(vlabel->i3_file);
   if (clus_numb == NULL) {
      (void) fprintf(stderr,"vlabel: cluster number image could not be read\n\n");
      exit(1);
      }
   (void) proper_num_images(program,clus_numb,1,TRUE);
   (void) proper_map_enable(program,clus_numb,VFF_MAP_OPTIONAL,TRUE);

   if (clus_numb ->data_storage_type != VFF_TYP_4_BYTE) {
      (void) fprintf(stderr,
      "vlabel: cluster number image has to be a INT image\n\n");
      exit(1);
      }


   nc = clus_numb->row_size;
   nr = clus_numb->col_size;

   if ((vlabel->w_int > (nc/2))  ||
       (vlabel->w_int > (nr/2))   )  {
      (void) fprintf(stderr,"vlabel:border too large for clus_numb size \n\n");
      exit(1);
      }
   }


if ((vlabel->i1_flag == TRUE) && (vlabel->i3_flag == TRUE)) {
   if (   (clus_numb->row_size != image->row_size) ||
          (clus_numb->col_size != image->col_size) ) {
      (void) fprintf(stderr,"vlabel: cluster and normal image must have the same dimension\n\
n");
      exit(1);
      }
   }


if ((vlabel->i2_flag == TRUE) && (vlabel->i3_flag == FALSE)) {
   (void) fprintf(stderr,"vlabel: cluster number image is missing\n\n");
   exit(1);
   }
if ((vlabel->i1_flag==TRUE)&&(vlabel->i2_flag==TRUE)&&(vlabel->i3_flag==TRUE)) {
   (void) fprintf(stderr,
           "vlabel: unable to process labelling with 3 inputs\n\n");
   exit(1);
   }

/* set the distance metrics */
if (vlabel->m_flag == TRUE) dist = vlabel->m_toggle;
else dist = 1;

/* set the connectivity, 4 connectivity, or, 8 connectivity */
if (vlabel->c_flag == TRUE) connect = vlabel->c_toggle;
else connect = 1;


/* check from argument which case has to be treated */
if ((vlabel->i1_flag == TRUE)   &&
    (vlabel->i2_flag == FALSE)  &&
    (vlabel->i3_flag == FALSE)  )   {
    cas = 0;       /* labelling from a multiband image */
    }
 else if ((vlabel->i1_flag  == FALSE) &&
          (vlabel->i2_flag  == TRUE)  &&
          (vlabel->i3_flag  == TRUE)  )     {
         cas = 1;  /* labelling from a clustering result */
         }
      else if ((vlabel->i1_flag == TRUE)   &&
               (vlabel->i2_flag == FALSE)  &&
               (vlabel->i3_flag == TRUE))    {
              cas = 2;/*labelling from clustering helped by multiband image*/
              }

/* Allocate space for output image (labelled image) */
label = createimage(nr,nc, VFF_TYP_4_BYTE, 1,
                     1,dummy, 0, 0, VFF_MS_NONE,
                     VFF_MAPTYP_NONE, VFF_LOC_IMPLICIT, 0);

if (label == NULL) {
   (void) fprintf(stderr,"vlabel: Unable to allocate new image!\\n");
   exit(1);
   }

/* check if automatic labelling required ( expected number of region) */
if (vlabel->n_flag == TRUE) {
   opt_auto = TRUE;
   region_number = vlabel->n_int;
   }
else opt_auto = FALSE;

/* check if merging option selected or not ( case where too small rejion */
/* are coinsidered UNDEFINED or are included in bigger ones).............*/
if (vlabel->merge_flag == FALSE) merge = TRUE;
else 
{
   if (vlabel->merge_logic == 1) merge = TRUE;
   else merge = FALSE;
}

/* ASCII file for labelling results display */
if (vlabel->asc_flag == TRUE) 
{
   if (vlabel->asc_file)
   {
      if (!vwrite_ascii (vlabel->asc_file, &printdev)) 
      {
            (void) fprintf (stderr, "vlabel:  Can't open ascii output file: \n");
            exit (1);
      }
   }
   else printdev = stdout;
}
else printdev = stdout;
/* -main_before_lib_call_end */

/* -main_library_call */
if (! lvlabel(image,
              clus_cent,
              clus_numb,
              cas,
              dist,
              connect,
              vlabel->w_int,
              label,
              vlabel->s_float,
              opt_auto,
              region_number,
              vlabel->f_float,
              merge,
              printdev))   {
       (void) fprintf(stderr, "lvlabel  Failed\\n");
       exit(1);
   }
/* -main_library_call_end */

/* -main_after_lib_call */
    writeimage(vlabel->o_file,label);
/* -main_after_lib_call_end */


	khoros_close();
}


/****************************************************************
*
* Routine Name:  gw_usage 
*
*
* Purpose:  prints out the usage for vlabel 
*
* Input:  none 
*
* Output:  none 
*
* Written By:  automatically generated by ghostwriter
*
****************************************************************/


gw_usage()
{
	fprintf(stderr, "vlabel :\n");
	fprintf(stderr, "\t\n");
	fprintf(stderr, "\tPerforms a Labeling on Multiband or Cluster Images\n");
	fprintf(stderr, "\t\n");
	fprintf(stderr, "\t\n");

/* -usage_additions */
/* -usage_additions_end */

	fprintf(stderr,"\t-o  output image after the labelling process  (outfile)\n");
	fprintf(stderr,"\t-merge  if flag= 1 the small regions will be merged together in connex regions, or will be included to existing labelled regions  (boolean)\n");
	fprintf(stderr, "\t-m  ");
	fprintf(stderr, "1 for euclidean distance, 2 for city block\n  ");
	fprintf(stderr, "\t\t1  (Use the Euclidean Distance),\n");
	fprintf(stderr, "\t\tor 2  (Use the City block Distance)\n");
	fprintf(stderr, "\n");
	fprintf(stderr, "\t-c  ");
	fprintf(stderr, "1 for the 4 connectivity, 2 for 8 connectivity\n  ");
	fprintf(stderr, "\t\t1  (if Yes use the 4 Connectivity),\n");
	fprintf(stderr, "\t\tor 2  (if Yes use the 8 Connectivity)\n");
	fprintf(stderr, "\n");
	fprintf(stderr, "\n");
	fprintf(stderr,"\t-i1  input image  (infile) -OR- \n");
	fprintf(stderr,"\t-i2  input image for cluster centers  (infile) \n");
	fprintf(stderr,"\t-n  Number of region that the user wishes to get from the labelling process  (integer, 2 to 2500) -OR- \n");
	fprintf(stderr,"\t-f  the higher the factor the finer the regions  (float,  0.000 to 1.000) \n");
	fprintf(stderr, "\n");
	fprintf(stderr,"\t[-i3]  input image for cluster numbers (infile) [null]\n");
	fprintf(stderr,"\t[-asc]  output file for vlabel result display (outfile) [null]\n");
	fprintf(stderr,"\t[-w]  specifies the border width in pixels (default = 0) (integer, 0 to 16) [0]\n");
	fprintf(stderr,"\t[-s]  Minimum number of pixel to keep in label region (float,  0.000 to 100.000) [1]\n");
	fprintf(stderr, " \n");
	fprintf(stderr, "\n");
	fprintf(stderr, "\t[-V] Gives the version for vlabel\n");
	fprintf(stderr, "\t[-U] Gives the usage for vlabel\n");
	fprintf(stderr, "\t[-P] Prompts for command line options\n");
	fprintf(stderr, "\t[-A [file1]] Creates the answer file called vlabel.ans or file1 \n");
	fprintf(stderr, "\t[-a [file1]] Uses vlabel.ans or file1 as the answer file \n\n\n");

}


/****************************************************************
*
* Routine Name:  gw_getargs 
*
*
* Purpose:  gets arguments off command line for vlabel
*
* Input:  none 
*
* Output:  none 
*
* Written By:  automatically generated by ghostwriter
*
****************************************************************/


gw_get_args()
{

char	*o_pstr = 
	"\nEnter: (o) output image after the labelling process \n        {outfile}: "; 
char	*merge_pstr = 
	"\nEnter: (merge) if flag= 1 the small regions will be merged together in connex regions, or will be included to existing labelled regions \n        {boolean, (y/n) }: "; 
char	*m_pstr = "\nEnter: (m) 1 for euclidean distance, 2 for city block -- \n      \t\t1 (Use the Euclidean Distance)\n\t\tor 2 (Use the City block Distance)\n     : "; 
char	*c_pstr = "\nEnter: (c) 1 for the 4 connectivity, 2 for 8 connectivity -- \n      \t\t1 (if Yes use the 4 Connectivity)\n\t\tor 2 (if Yes use the 8 Connectivity)\n     : "; 
char	*i1_pstr = 
	"\nEnter: (i1) input image \n        {infile}: "; 
char	*i2_pstr = 
	"\nEnter: (i2) input image for cluster centers \n        {infile}: "; 
char	*n_pstr = 
	"\nEnter: (n) Number of region that the user wishes to get from the labelling process \n        {integer, 2 to 2500 [10] }: "; 
char	*f_pstr = 
	"\nEnter: (f) the higher the factor the finer the regions \n        {float,  0.000 to 1.000 [0.070000] }: "; 
char	*i3_pstr = 
	"\nEnter: (i3) input image for cluster numbers \n        {infile}: "; 
char	*asc_pstr = 
	"\nEnter: (asc) output file for vlabel result display \n        {outfile}: "; 
char	*w_pstr = 
	"\nEnter: (w) specifies the border width in pixels (default = 0) \n        {integer, 0 to 16 [0] }: "; 
char	*s_pstr = 
	"\nEnter: (s) Minimum number of pixel to keep in label region \n        {float,  0.000 to 100.000 [1.000000] }: "; 
char  answer_file[512], temp[512];



int	fid = -1,
	error, query, ok, count;
	int prompt_flag = FALSE;

	/*
	 * print version if necessary
	 */
	vgparml(fid, "-V", "noprompt", &query, 0, 0, &error);
	if (error == 0)
	{
	    printf ("\n%s: %s: Version %d.%d\n\n",
	    "vlabel", RELEASE_NAME, RELEASE_MAJOR, RELEASE_MINOR);
	    exit(1);
	}

	/*
	 * print usage if necessary
	 */
	vgparml(fid, "-U", "noprompt", &query, 0, 0, &error);
	if (error == 0)
	{
	    gw_usage();
	    exit(1);
	}

	/*
	 * see if interactive prompting is desired
	 */
	vgparml(fid, "-P", "noprompt", &query, 0, 0, &error);
	if (error == 0)
	    prompt_flag = TRUE;

	/*
	 * see if answer file is to be used
	 */
	vgparms(fid, "-a", "noprompt", answer_file, 0, 0, &error);
	if (error == 0)
	{
	     if (VStrlen(answer_file) == 0)
		sprintf(answer_file, "vlabel.ans");
	     while (fid < 0)
	     {
		if ((fid = open(answer_file, O_RDONLY, 0666))== -1)
		{
		    fprintf(stderr, "vlabel: can't open answer file \"%s\"",
			    answer_file); 
		    fprintf(stderr, "please re-enter: ");
		    (void) gets(answer_file);
		    if (VStrlen(answer_file) == 0)
			sprintf(answer_file, "vlabel.ans");
		}

	     }

	}

	/*
	 * allocate the vlabel structure
	 */
	vlabel = (vlabel_struct *) 
	       calloc((unsigned)1, (unsigned) sizeof (vlabel_struct));

	/*
	 * get required arguments for vlabel
	 */
	if (prompt_flag == TRUE)
	    fprintf(stderr,"\nRequired Arguments:\n\n");

	if (!(vlabel->o_flag = vget_outfile(fid, prompt_flag,
			"-o", o_pstr, &(vlabel->o_file))
))
	{
	    if (prompt_flag == TRUE)
	    {
		while(!(vlabel->o_flag))
		{
		    fprintf(stderr, "\t\to is required, please re-enter: \n");
		    vlabel->o_flag = vget_outfile(fid, prompt_flag,
		    "-o", o_pstr, &(vlabel->o_file))
;

		}
	    }
	    else
	    {
		fprintf(stderr, "Error: '-o' is a required argument\n");
		gw_usage();
		exit(1);
	    }
	}

	if (!(vlabel->merge_flag = vget_logic(fid, prompt_flag,
			"-merge", merge_pstr, &(vlabel->merge_logic), 0)))
	{
	    if (prompt_flag == TRUE)
	    {
		while(!(vlabel->merge_flag))
		{
		    fprintf(stderr, "\t\tmerge is required, please re-enter: \n");
		    vlabel->merge_flag = vget_logic(fid, prompt_flag,
		    "-merge", merge_pstr, &(vlabel->merge_logic), 0);

		}
	    }
	    else
	    {
		fprintf(stderr, "Error: '-merge' is a required argument\n");
		gw_usage();
		exit(1);
	    }
	}


	/*
	 * get required toggles for vlabel
	 */
	if (prompt_flag == TRUE)
	{
	    ok = FALSE;
	    while(!ok)
	    {
		vlabel->m_flag = vget_int(fid, prompt_flag,
		"-m", m_pstr, &(vlabel->m_toggle),
		1, 0, 0);

		if (((vlabel->m_toggle == 1 ) || 
		     (vlabel->m_toggle == 2 )) &&
		     (vlabel->m_flag))
		      ok = TRUE;
		else
		{
		    fprintf(stderr, "\nm is a required argument.\n");
		}
	    }
	    ok = FALSE;
	    while(!ok)
	    {
		vlabel->c_flag = vget_int(fid, prompt_flag,
		"-c", c_pstr, &(vlabel->c_toggle),
		1, 0, 0);

		if (((vlabel->c_toggle == 1 ) || 
		     (vlabel->c_toggle == 2 )) &&
		     (vlabel->c_flag))
		      ok = TRUE;
		else
		{
		    fprintf(stderr, "\nc is a required argument.\n");
		}
	    }
	}
	else
	{
		vlabel->m_flag = vget_int(fid, prompt_flag,
		"-m", m_pstr, &(vlabel->m_toggle),
		1, 0, 0);

		if (((vlabel->m_toggle != 1 ) && 
		     (vlabel->m_toggle != 2 )) ||
		     (!(vlabel->m_flag)))
		{
		    fprintf(stderr, "m is a required argument.\n");
		    fprintf(stderr, "\n");
		    gw_usage();
		    exit(0);
		}
		vlabel->c_flag = vget_int(fid, prompt_flag,
		"-c", c_pstr, &(vlabel->c_toggle),
		1, 0, 0);

		if (((vlabel->c_toggle != 1 ) && 
		     (vlabel->c_toggle != 2 )) ||
		     (!(vlabel->c_flag)))
		{
		    fprintf(stderr, "c is a required argument.\n");
		    fprintf(stderr, "\n");
		    gw_usage();
		    exit(0);
		}
	}

	/*
	 * get required mutually exclusive groups for vlabel
	 */
	if (prompt_flag == TRUE)
	{
		   fprintf(stderr, "\nThe following prompts are mutually exclusive.\n");
		   fprintf(stderr, "\nHit <cr> until the desired prompt appears.\n");
	   ok = FALSE;
	   while(!ok)
	   {
		vlabel->i1_flag = vget_infile(fid, prompt_flag,
		    "-i1", i1_pstr, &(vlabel->i1_file))
;

    		if(!( (vlabel->i1_flag)))
		    vlabel->i2_flag = vget_infile(fid, prompt_flag,
		    "-i2", i2_pstr, &(vlabel->i2_file))
;

		if((vlabel->i1_flag)|| 
		    (vlabel->i2_flag))
		    ok = TRUE;
		else
		{
		   fprintf(stderr, "Error: You MUST specify one of :\n");
		    fprintf(stderr, " -i1  -i2 \n");
		}
	   }
	   ok = FALSE;
	   while(!ok)
	   {
		vlabel->n_flag = vget_int(fid, prompt_flag,
		    "-n", n_pstr, &(vlabel->n_int),
		    10, 2, 2500);

    		if(!( (vlabel->n_flag)))
		    vlabel->f_flag = vget_float(fid, prompt_flag,
		    "-f", f_pstr, &(vlabel->f_float),
		    0.070000, 0.000000, 1.000000);

		if((vlabel->n_flag)|| 
		    (vlabel->f_flag))
		    ok = TRUE;
		else
		{
		   fprintf(stderr, "Error: You MUST specify one of :\n");
		    fprintf(stderr, " -n  -f \n");
		}
	   }
		   fprintf(stderr, "\n ------\n");
	}
	else
	{
		count = 0;
		if(vlabel->i1_flag = vget_infile(fid, prompt_flag,
		    "-i1", i1_pstr, &(vlabel->i1_file))
)
		    count++;

		if(vlabel->i2_flag = vget_infile(fid, prompt_flag,
		    "-i2", i2_pstr, &(vlabel->i2_file))
)
		    count++;

		if (count == 0)
		{
		    fprintf(stderr, "Error: You MUST specify one of :\n");
		    fprintf(stderr, " -n  -f \n");
		    gw_usage();
		    exit(1);
		}

		else if (count > 1)
		{
		    fprintf(stderr, "Error: You may specify ONLY ONE of :\n");
		    fprintf(stderr, " -n  -f \n");
		    gw_usage();
		    exit(1);
		}

		count = 0;
		if(vlabel->n_flag = vget_int(fid, prompt_flag,
		    "-n", n_pstr, &(vlabel->n_int),
		    10, 2, 2500))
		    count++;

		if(vlabel->f_flag = vget_float(fid, prompt_flag,
		    "-f", f_pstr, &(vlabel->f_float),
		    0.070000, 0.000000, 1.000000))
		    count++;

		if (count == 0)
		{
		    fprintf(stderr, "Error: You MUST specify one of :\n");
		    fprintf(stderr, " -n  -f  -€  - \n");
		    gw_usage();
		    exit(1);
		}

		else if (count > 1)
		{
		    fprintf(stderr, "Error: You may specify ONLY ONE of :\n");
		    fprintf(stderr, " -n  -f  -Ò  - \n");
		    gw_usage();
		    exit(1);
		}

	}

	/*
	 * get optional arguments for vlabel
	 */
	if (prompt_flag == TRUE)
	   fprintf(stderr,"\nOptional Arguments:\n\n");

	vlabel->i3_flag = vget_infile(fid, prompt_flag,
	"-i3", i3_pstr, &(vlabel->i3_file))
;

	vlabel->asc_flag = vget_outfile(fid, prompt_flag,
	"-asc", asc_pstr, &(vlabel->asc_file))
;

	vlabel->w_flag = vget_int(fid, prompt_flag,
	"-w", w_pstr, &(vlabel->w_int),
	0, 0, 16);

	vlabel->s_flag = vget_float(fid, prompt_flag,
	"-s", s_pstr, &(vlabel->s_float),
	1.000000, 0.000000, 100.000000);


}



