/*******************************************************************************
 *                                                                             *
 *  Filename : popular.c                                                       *
 *  Author   : Bruno Grossniklaus                                              *
 *  Created  : 15.4.91                                                         *
 *  Modified :                                                                 *
 *             20.6.91 Gro: bug fixed if filename is not given                 *
 *                                                                             *
 *                                                                             *
 ******************************************************************************/

/*
 * popular.c
 *
 * Transforms 32 or 24 Bit pixrect or rayshade files to 8 Bit colormap files
 * with the popularity algorithm
 *
 */

/******************************************************************** INCLUDE */
/* global defaults are set in defaults.h */
#include <stdio.h>
/* This version is for use with XView only! */
#include <pixrect/pixrect_hs.h>
#include "defaults.h"


/******************************************************************** DEFINE  */
/* defaults for popular */
/* more defaults are included in defaults.h */

#define  VERSION  "1.02 (20.6.91)"        /* Versions Nr.                     */

#define  DEFAULT_HISTOGRAM   FALSE        /* Default write histogram to stdout*/

#define  DEFAULT_SHIFT_R     2            /* Default shift for red            */
#define  DEFAULT_SHIFT_G     2            /* Default shift for green          */
#define  DEFAULT_SHIFT_B     2            /* Default shift for blue           */

#define  DEFAULT_EUCLID_MIN  0            /* Default min of euclid. dist      */
#define  MAX_EUCLID          999          /* Default max of euclid. dist      */

#define  DEFAULT_OPTIMIZE    FALSE        /* Default optimization             */
#define  OPT_START           100          /* start eucl. dist if optimization */
#define  OPT_UP              50           /* increment for optimization       */
#define  OPT_DOWN            10           /* decrement for optimization       */
#define  UP                  1            /* used for optimization (scan_dir) */
#define  DOWN                2            /* used for optimization (scan_dir) */


/********************************************************************* TYPES  */
/* types for popular */
typedef struct {                          /* Type of histogram                */
  long int           n;                   /* number to count colors           */
} HIST_T;                                 /* and keeps colormap_index         */
                                          /* ( -1 is possible for init.)      */


/****************************************************************** FUNCTIONS */
/* functions in pic_io.c */
extern void set_file_names();
extern void close_success();
extern void close_error();
extern int  open_in_file();
extern int  open_out_file();
extern int  get_image();
extern int  get_mem();
extern int  put_image();
extern void print_euclidean_dist();
extern void write_map();


/*******************************************************************************
 *   main                                                                      *
 *                                                                             *
 *   Input  :                                                                  *
 *            - argv      arguments (options and filename)                     *
 *            - argc      number of arguments                                  *
 *                                                                             *
 *   Return : - NULL if ok, 1 on error                                         *
 *                                                                             *
 ******************************************************************************/

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

{
/******************************************************************** DEKLAR  */
  FILE                *fp_in;             /* file pointer                     */
  FILE                *fp_out;            /* file pointer                     */
  char                fn_in[FNS];         /* file name input                  */
  char                fn_out[FNS];        /* file name output                 */
  char                tmp_str[16];        /* temorary string                  */

  Pixrect             *mem_8_out;         /* pixrect in memory 8 Bit          */
  Pixrect             *mem_in;            /* pixrect in memory 24 or 32 Bit   */

  colormap_t          colormap;           /* colormap of output file          */
  unsigned char       red[256];           /* used for colormap                */
  unsigned char       green[256];         /* used for colormap                */
  unsigned char       blue[256];          /* used for colormap                */
  int                 color_index;        /* index in colormap                */
  int                 col_map_max;        /* max of colormap values           */
  int                 num_colors;         /* number of different colors       */

  unsigned char       *im_ptr_8_out;      /* pointer into 8 Bit image         */
  int                 *im_ptr_in;         /* pointer into 24 or 32 Bit image  */

  int                 x,y,depth;          /* size and depth of image          */
  int                 out_format;         /* outfileformat (standard,encoded) */
  int                 i,j,k,l;            /* used for loops                   */
  register long int   r,g,b;              /* value of red,green,blue          */

  unsigned char       flag_prompt;        /* flag if prompt                   */
  unsigned char       flag_euclid;        /* flag if calculate euclid         */
  unsigned char       flag_expand_name;   /* flag if expand name              */
  unsigned char       flag_option_ok;     /* flag if option ok                */
  unsigned char       flag_write_map;     /* flag if write colormap           */
  unsigned char       flag_stdout;        /* flag if write to stdout          */
  unsigned char       flag_sunview;       /* flag if sunview                  */
  unsigned char       flag_euclid_min;    /* flag if minimize euclid. dist    */
  unsigned char       flag_histogram;     /* flag if write histogram to stdout*/
  unsigned char       flag_optimize;      /* flag if optimization             */
  unsigned char       flag_floyd_steinb;  /* flag if floyd steinberg dither   */
  unsigned char       flag_percent;       /* for faster access                */

  unsigned char       scan_direction;     /* used for optimization            */
  HIST_T              *histogram;         /* pointer into histogram           */
  int                 hist_size;          /* size of histogram                */
  register unsigned long int
                      hist_index;         /* index for histogram              */
  int                 euclid_min;         /* min of euclid. dist              */
  int                 list_next[257];     /* used as pointer to next in list  */
  unsigned char       list_color_r[256];  /* red value in list                */
  unsigned char       list_color_b[256];  /* blue value in list               */
  unsigned char       list_color_g[256];  /* green value in list              */
  long int            list_num_col[257];  /* number of colors in list         */

  unsigned char       shift_r;            /* shift for red                    */
  unsigned char       shift_g;            /* shift for green                  */
  unsigned char       shift_b;            /* shift for blue                   */

  register unsigned char
     red_r,green_r,green_l,blue_r,blue_l; /* for fast access in loops         */

  unsigned int
     get_red, get_green, get_blue;        /* to get color from hist_index     */

  register long int   euclid_min_dist;    /* to calculate euclid. dist        */
  register long int   euclid_mom_dist;    /* dito                             */
  register int        euclid_tmp;         /* dito                             */

  int                 *error_r;           /* red scanline error               */
  int                 *error_g;           /* green scanline error             */
  int                 *error_b;           /* blue scanline error              */
  int                 hori_err_r;         /* horizontal error red             */
  int                 hori_err_g;         /* horizontal error green           */
  int                 hori_err_b;         /* horizontal error blue            */
  int                 diag_err_r;         /* diagonal error red               */
  int                 diag_err_g;         /* diagonal error green             */
  int                 diag_err_b;         /* diagonal error blue              */
  int                 curr_err_r;         /* current error red                */
  int                 curr_err_g;         /* current error green              */
  int                 curr_err_b;         /* current error blue               */
  register int
                      spread_hori,        /* spreading of errors              */
                      spread_diag,
                      spread_vert;
  register int        hundred;            /* spreading of errors              */
  register int        spread_percent;     /* spread error in %                */


/******************************************************************** INIT    */
  /* set variables with defaults (defined in defaults.h) */

  /* file names with EOS (end of string) */
  for (i = 0; i < FNS; i++) fn_in[i] = fn_out[i] = '\0';

  /* pointers with NULL */
  fp_in = fp_out = NULL;
  mem_8_out = mem_in = NULL;

  /* set default shift */
  shift_r = DEFAULT_SHIFT_R;
  shift_g = DEFAULT_SHIFT_G;
  shift_b = DEFAULT_SHIFT_B;

  /* other default values */
  flag_histogram = DEFAULT_HISTOGRAM;
  out_format = DEFAULT_OUT_FORM;
  flag_prompt = DEFAULT_PROMPT;
  flag_euclid = DEFAULT_EUCLID;
  flag_expand_name = DEFAULT_EXP_NAM;
  flag_write_map = DEFAULT_WRITE_MAP;
  if (DEFAULT_EUCLID_MIN == 0)
    flag_euclid_min = FALSE;
  else flag_euclid_min = TRUE;
  euclid_min = DEFAULT_EUCLID_MIN;
  flag_optimize = DEFAULT_OPTIMIZE;
  flag_stdout = FALSE;
  flag_sunview = DEFAULT_SUNVIEW;


  /* set default for floyd steinberg dither */
  flag_floyd_steinb = DEFAULT_FLOYD;
  spread_hori = DEFAULT_SPREAD_HORI;
  spread_diag = DEFAULT_SPREAD_DIAG;
  spread_vert = 100 - spread_hori - spread_diag;
  hundred = 100;
  spread_percent = DEFAULT_SPREAD_PERCENT;

  fprintf (stderr,"\n");


/******************************************************************** OPTIONS */
  /* argv[0] is name of program */
  /* if there are no parameters specified show usage */
  if (argc <= 1) {
    fprintf (stderr,"Called without parameters \n");
    usage_exit (argv[0]);
  }

  /* the last parameter is the input file name or the -h option */
  else if (argv[argc - 1] [0] != '-')
      strcpy (fn_in,argv[argc - 1]);
    else
      if (strcmp (argv[argc - 1], "-h") == 0) help_exit (argv[0]);
      else if (strcmp (argv[argc - 1],"-c") == 0) {
        fprintf (stderr,"%s was written by Bruno Grossniklaus in 1991\n",
                         argv[0]);
        exit (1);
      }
      else {
        fprintf (stderr,"Last parameter %s is not filename (but option) \n",
                                                                  argv[argc-1]);
        usage_exit (argv[0]);
      }


  /* scan the options */
  i=1;
  flag_option_ok = TRUE;

  while ( (i < argc - 1) && (flag_option_ok) ) {
    flag_option_ok = FALSE;

    if (strcmp (argv[i],"-p+") == 0) {
      i++;
      flag_option_ok = TRUE;
      flag_prompt = TRUE;
    }

    if (strcmp (argv[i],"-p-") == 0) {
      i++;
      flag_option_ok = TRUE;
      flag_prompt = FALSE;
    }

    if (strcmp (argv[i],"-p") == 0) {
      i++;
      flag_option_ok = TRUE;
      flag_prompt = !flag_prompt;
    }


    if (strcmp (argv[i],"-o") == 0) {
      flag_option_ok = TRUE;
      i++;
      if (i >= argc - 1) {
        fprintf (stderr,"Missing parameter after %s. \n",argv[i-1]);
        fprintf (stderr,"%s is the input filename! \n",argv[i]);
        usage_exit (argv[0]);
      }
      strcpy (fn_out,argv[i]);
      if ( (fn_out[0] == '-') || (fn_out == NULL) ) {
        fprintf (stderr,"Parameter %s after -o is not filename \n",fn_out);
        usage_exit (argv[0]);
      }
      i++;
    }


    if (strcmp (argv[i],"-en+") == 0) {
      i++;
      flag_option_ok = TRUE;
      flag_expand_name = TRUE;
    }

    if (strcmp (argv[i],"-en-") == 0) {
      i++;
      flag_option_ok = TRUE;
      flag_expand_name = FALSE;
    }

    if (strcmp (argv[i],"-en") == 0) {
      i++;
      flag_option_ok = TRUE;
      flag_expand_name = !flag_expand_name;
    }


    if ( (strcmp (argv[i],"-ws+") == 0) || (strcmp (argv[i],"-ws") == 0) ) {
      flag_option_ok = TRUE;
      out_format = RT_STANDARD;
      if (flag_prompt) fprintf (stderr,"Output file format is STANDARD \n");
      i++;
    }

    if (strcmp (argv[i],"-ws-") == 0) {
      flag_option_ok = TRUE;
      out_format = RT_BYTE_ENCODED;
      if (flag_prompt)
            fprintf (stderr,"Output file format is RUN LENGTH ENCODED \n");
      i++;
    }


    if (strcmp (argv[i],"-sv+") == 0) {
      i++;
      flag_option_ok = TRUE;
      flag_sunview = TRUE;
    }

    if (strcmp (argv[i],"-sv-") == 0) {
      i++;
      flag_option_ok = TRUE;
      flag_sunview = FALSE;
    }

    if (strcmp (argv[i],"-sv") == 0) {
      i++;
      flag_option_ok = TRUE;
      flag_sunview = !flag_sunview;
    }


    if (strcmp (argv[i],"-sa") == 0) {
      i++;
      flag_option_ok = TRUE;
      if (i >= argc - 1) {
        fprintf (stderr,"Missing parameter after %s. \n",argv[i-1]);
        fprintf (stderr,"%s is the input filename! \n",argv[i]);
        usage_exit (argv[0]);
      }
      if ( (atoi(argv[i]) < 0) || (atoi(argv[i]) > 8) ) {
        fprintf (stderr," %d is not allowed for %s \n",atoi(argv[i]),argv[i-1]);
        usage_exit (argv[0]);
      }
      else {
        shift_r = atoi(argv[i]);
        shift_g = atoi(argv[i]);
        shift_b = atoi(argv[i]);
      }
      i++;
    }

    if (strcmp (argv[i],"-sr") == 0) {
      i++;
      flag_option_ok = TRUE;
      if (i >= argc - 1) {
        fprintf (stderr,"Missing parameter after %s. \n",argv[i-1]);
        fprintf (stderr,"%s is the input filename! \n",argv[i]);
        usage_exit (argv[0]);
      }
      if ( (atoi(argv[i]) < 0) || (atoi(argv[i]) > 8) ) {
        fprintf (stderr," %d is not allowed for %s \n",atoi(argv[i]),argv[i-1]);
        usage_exit (argv[0]);
      }
      else shift_r = atoi(argv[i]);
      i++;
    }

    if (strcmp (argv[i],"-sg") == 0) {
      i++;
      flag_option_ok = TRUE;
      if (i >= argc - 1) {
        fprintf (stderr,"Missing parameter after %s. \n",argv[i-1]);
        fprintf (stderr,"%s is the input filename! \n",argv[i]);
        usage_exit (argv[0]);
      }
      if ( (atoi(argv[i]) < 0) || (atoi(argv[i]) > 8) ) {
        fprintf (stderr," %d is not allowed for %s \n",atoi(argv[i]),argv[i-1]);
        usage_exit (argv[0]);
      }
      else shift_g = atoi(argv[i]);
      i++;
    }

    if (strcmp (argv[i],"-sb") == 0) {
      i++;
      flag_option_ok = TRUE;
      if (i >= argc - 1) {
        fprintf (stderr,"Missing parameter after %s. \n",argv[i-1]);
        fprintf (stderr,"%s is the input filename! \n",argv[i]);
        usage_exit (argv[0]);
      }
      if ( (atoi(argv[i]) < 0) || (atoi(argv[i]) > 8) ) {
        fprintf (stderr," %d is not allowed for %s \n",atoi(argv[i]),argv[i-1]);
        usage_exit (argv[0]);
      }
      else shift_b = atoi(argv[i]);
      i++;
    }


    if (strcmp (argv[i],"-edm") == 0) {
      i++;
      flag_option_ok = TRUE;
      flag_euclid_min = TRUE;
      if (i >= argc - 1) {
        fprintf (stderr,"Missing parameter after %s. \n",argv[i-1]);
        fprintf (stderr,"%s is the input filename! \n",argv[i]);
        usage_exit (argv[0]);
      }
      if ( (atoi(argv[i]) < 0) || (atoi(argv[i]) > MAX_EUCLID) ) {
        fprintf (stderr," %d is not allowed for %s \n",atoi(argv[i]),argv[i-1]);
        fprintf (stderr," (0 <= x <= %d) \n",MAX_EUCLID);
        usage_exit (argv[0]);
      }
      else euclid_min = atoi(argv[i]) ;
      i++;
    }


    if (strcmp (argv[i],"-opt") == 0) {
      i++;
      flag_option_ok = TRUE;
      flag_optimize  = TRUE;
      if ( (argv[i][0] == '-') || (i >= argc - 1) )
      euclid_min = OPT_START;
      else {
        if ( (atoi(argv[i]) < 0) || (atoi(argv[i]) > MAX_EUCLID) ) {
          fprintf (stderr," %d is not allowed for %s \n",atoi(argv[i]),
                           argv[i-1]);
          fprintf (stderr," (0 <= x <= %d) \n",MAX_EUCLID);
          usage_exit (argv[0]);
        }
        else euclid_min = atoi(argv[i]) ;
        i++;
      }
    }


    if (strcmp (argv[i],"-fs%") == 0) {
      i++;
      flag_option_ok = TRUE;
      if (i >= argc - 1) {
        fprintf (stderr,"Missing parameter after %s. \n",argv[i-1]);
        fprintf (stderr,"%s is the input filename! \n",argv[i]);
        usage_exit (argv[0]);
      }
      if ( (argv[i][0] == '-') || (i >= argc - 1) ) {
        fprintf (stderr,"Missing parameter after %s. \n",argv[i-1]);
        usage_exit (argv[0]);
      }
      else {
        spread_percent = atoi (argv[i]);
        if ( (spread_percent < 0) || (spread_percent > 100) ) {
          fprintf (stderr,"After -fs%% must be a number in percent. ");
          fprintf (stderr,"%d not allowed\n",spread_percent);
          usage_exit (argv[0]);
        }
      }
      i++;
    }

    if (strcmp (argv[i],"-fs+") == 0) {
      i++;
      flag_option_ok = TRUE;
      flag_floyd_steinb = TRUE;
      if ( (argv[i][0] != '-') && (i < argc - 1) ) {
        spread_hori = atoi (argv[i]);
        i++;
        if ( (argv[i][0] == '-') || (i >= argc - 1) ) {
          fprintf (stderr,"Missing parameter after %s. \n",argv[i-2]);
          fprintf (stderr,"%s must be diagonal spreading! \n",argv[i]);
          usage_exit (argv[0]);
        }
        spread_diag = atoi (argv[i]);
        i++;
      }
      if ( (spread_hori < 0) || (spread_hori > 100) ) {
        fprintf (stderr,"Horizontal spreading is ");
        fprintf (stderr,"%d, but must be >= 0 and <= 100!\n",spread_hori);
        usage_exit (argv[0]);
      }
      if ( (spread_diag < 0) || (spread_diag > 100) ) {
        fprintf (stderr,"Diagonal spreading is ");
        fprintf (stderr,"%d, but must be >= 0 and <= 100!\n",spread_diag);
        usage_exit (argv[0]);
      }
      spread_vert = 100 - spread_hori - spread_diag;
      if (spread_vert < 0) {
        fprintf (stderr,"Vertical spreading is %d, but must be >= 0!\n",
                 spread_vert);
        usage_exit (argv[0]);
      }
    }

    if (strcmp (argv[i],"-fs-") == 0) {
      i++;
      flag_option_ok = TRUE;
      flag_floyd_steinb = FALSE;
    }

    if (strcmp (argv[i],"-fs") == 0) {
      i++;
      flag_option_ok = TRUE;
      flag_floyd_steinb = !flag_floyd_steinb;
      if (flag_floyd_steinb) {
        if ( (argv[i][0] != '-') && (i < argc - 1) ) {
          spread_hori = atoi (argv[i]);
          i++;
          if ( (argv[i][0] == '-') || (i >= argc - 1) ) {
            fprintf (stderr,"Missing parameter after %s. \n",argv[i-2]);
            fprintf (stderr,"%s must be diagonal spreading! \n",argv[i]);
            usage_exit (argv[0]);
          }
          spread_diag = atoi (argv[i]);
          i++;
        }
        if ( (spread_hori < 0) || (spread_hori > 100) ) {
          fprintf (stderr,"Horizontal spreading is ");
          fprintf (stderr,"%d, but must be >= 0 and <= 100!\n",spread_hori);
          usage_exit (argv[0]);
        }
        if ( (spread_diag < 0) || (spread_diag > 100) ) {
          fprintf (stderr,"Diagonal spreading is ");
          fprintf (stderr,"%d, but must be >= 0 and <= 100!\n",spread_diag);
          usage_exit (argv[0]);
        }
        spread_vert = 100 - spread_hori - spread_diag;
        if (spread_vert < 0) {
          fprintf (stderr,"Vertical spreading is %d, but must be >= 0!\n",
                   spread_vert);
          usage_exit (argv[0]);
        }
      }
    }


    if (strcmp (argv[i],"-ce+") == 0) {
      i++;
      flag_option_ok = TRUE;
      flag_euclid = TRUE;
    }

    if (strcmp (argv[i],"-ce-") == 0) {
      i++;
      flag_option_ok = TRUE;
      flag_euclid = FALSE;
    }

    if (strcmp (argv[i],"-ce") == 0) {
      i++;
      flag_option_ok = TRUE;
      flag_euclid = !flag_euclid;
    }

    if (strcmp (argv[i],"-hi") == 0) {
      i++;
      flag_option_ok = TRUE;
      flag_histogram = TRUE;
    }


    if (strcmp (argv[i],"-m+") == 0) {
      i++;
      flag_option_ok = TRUE;
      flag_write_map = TRUE;
    }

    if (strcmp (argv[i],"-m-") == 0) {
      i++;
      flag_option_ok = TRUE;
      flag_write_map = FALSE;
    }

    if (strcmp (argv[i],"-m") == 0) {
      i++;
      flag_option_ok = TRUE;
      flag_write_map = !flag_write_map;
    }


    if (strcmp (argv[i],"-h") == 0)
      help_exit (argv[0]);

  }


  /* if current parameter was no good option */
  if (!flag_option_ok) {
    fprintf (stderr,"%s is not an allowed option \n",argv[i]);
    usage_exit (argv[0]);
  }


/******************************************************************** INIT    */
  if (strcmp (fn_out,DEFAULT_STDOUT) == 0) flag_stdout = TRUE;

  /* function in pic_io.c */
  set_file_names (fn_in,fn_out);

  /* if expand name is set then add current settings to the output file name */
  if ( (flag_expand_name) && (!flag_stdout) ){

    /* p means popularity algorithm */
    strcat (fn_out,"_p_");

    /* add shift */
    sprintf (tmp_str,"%d", shift_r);
    strcat (fn_out,tmp_str);
    sprintf (tmp_str,"%d", shift_g);
    strcat (fn_out,tmp_str);
    sprintf (tmp_str,"%d", shift_b);
    strcat (fn_out,tmp_str);

    /* opt means optimization */
    if (flag_optimize) strcat (fn_out,"_opt");

    /* add euclid min */
    if ( (flag_euclid_min) && (!flag_optimize) ) {
      strcat (fn_out,"_");
      sprintf (tmp_str,"%d", euclid_min);
      strcat (fn_out,tmp_str);
    }

    /* add floyd steinbeg */
    if (flag_floyd_steinb) {
      strcat (fn_out,"_fs_");
      sprintf (tmp_str, "%d", spread_hori);
      strcat (fn_out,tmp_str);
      strcat (fn_out,"_");
      sprintf (tmp_str, "%d", spread_diag);
      strcat (fn_out,tmp_str);
      strcat (fn_out,"_");
      sprintf (tmp_str, "%d", spread_vert);
      strcat (fn_out,tmp_str);
      strcat (fn_out,"_");
      sprintf (tmp_str, "%d", spread_percent);
      strcat (fn_out,tmp_str);
      strcat (fn_out,"%");
    }

    /* print the output file name to console */
    fprintf (stderr,"Expand name is set. So output file is %s \n",fn_out);
  }


/***************************************************************** OPEN & GET */
  /* now open the files and load image */
  /* functions in pic_io.c */
  if (open_in_file (fn_in,&fp_in,fp_out,mem_in,mem_8_out) != NULL) exit (1);
  if (open_out_file (fn_out,fp_in,&fp_out,mem_in,mem_8_out) != NULL) exit (1);
  if (    get_image (fn_in,fp_in,fp_out,&mem_in,mem_8_out,
                     flag_prompt,&x,&y,&depth) != NULL) exit (1);

  /* allocate memory for output image */
  if (get_mem(fp_in,fp_out,mem_in,&mem_8_out,flag_prompt,x,y) != NULL) exit (1);


/*********************************************************** COLOR STATISTICS */
  /* set histogram size */
  hist_size = (256 >> shift_r) * (256 >> shift_g) * (256 >> shift_b);
  if (flag_prompt) fprintf (stderr,"Histogram size : %d \n",hist_size);

  if (flag_prompt) fprintf (stderr,"Sampling for color statistics ... ");

  if ( (histogram = (HIST_T *)
                    malloc ( (unsigned) hist_size  * sizeof (HIST_T))) == NULL) {
    fprintf (stderr,"\nError in malloc for histogram. \n");
    fprintf (stderr," Not enough memory!\n");
    free ( (char *) histogram);
    close_error (fp_in,fp_out,mem_in,mem_8_out);
    exit (1);
  }

  /* init histogram */
  for (hist_index = 0; hist_index < hist_size ; hist_index++)
    histogram[hist_index].n = 0;

  num_colors = 0;

  /* set registers for faster access */
  red_r   =      shift_r;
  green_r =  8 + shift_g;
  blue_r  = 16 + shift_b;
  green_l =  8 - shift_r;
  blue_l  = 16 - shift_r - shift_g;

  /* set pointer to first pixel */
  im_ptr_in = (int *) mpr_d(mem_in)->md_image;

  /* scan image and count the different colors */
  for (i = 0; i < x*y; i++, im_ptr_in++) {
    /* look for the coding to get histogram index */

    r =  ((*im_ptr_in) & 0x000000ff) >> red_r;
    g = (((*im_ptr_in) & 0x0000ff00) >> green_r) << green_l;
    b = (((*im_ptr_in) & 0x00ff0000) >> blue_r ) << blue_l;

    if (histogram[r + g + b].n++ == 0) {
      num_colors ++;
    }

  }
  if (flag_prompt) fprintf (stderr,"done. \n");
  if (flag_prompt) fprintf (stderr,"  Number of different colors : %d \n",
                            num_colors);


  /* get the colormap */

  /* if sunview option reserve 2 colors for sunview */
  if (num_colors > 256) num_colors = 256;
  if (flag_sunview) col_map_max = num_colors - 2; else col_map_max = num_colors;

  /* init variables if optimization */

  /* if there are less than 256 colors no optimization and no euclid. min */
  if (num_colors < 256) flag_optimize = flag_euclid_min = FALSE;

  /* for faster access => no if ( (flag_opti.) || (flag_eucl.) ) is used */
  if (flag_optimize) flag_euclid_min = TRUE;

  if (flag_optimize) scan_direction = UP;

  if ( (flag_prompt) && (!flag_optimize) ) 
                                      fprintf (stderr,"Choosing colormap ... ");
  if ( (flag_prompt) && (flag_optimize) )
                         fprintf (stderr,"Choosing colormap and optimize : \n");

  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
   * Label for goto                                                          *
   * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  TRYNEXT:

  for (i = 0; i <= col_map_max; i++) 
    { list_num_col[i] = 0; list_next[i] = i; }
  for (i = 0; i < col_map_max; i++) 
    list_color_r[i] = list_color_g[i] = list_color_b[i] = 0;

  /* used for faster access (no test in while loop necessary) */
  list_num_col[col_map_max] = 0xffffff;

  /* euclid_min is for one color pixel, but there are tree of them */
  euclid_min = euclid_min * 3;

  /* loop over all colors in histogram */
  /* list_next[0] is the index for the smallest number of colors in list */
  /* list_colors_x[] are the colors in list                              */
  /* list_num_col[] is number of colors in list                          */

  /* set registers for faster access */
  green_r =  8 - shift_r;
  blue_r  = 16 - shift_r - shift_g;

  get_red   = 255 >> shift_r;
  get_green = 255 >> shift_g;
  get_blue  = 255 >> shift_b;

  for (hist_index = 0; hist_index < hist_size; hist_index++)

    /* is current number of colors > smallest in list */
    if (histogram[hist_index].n > list_num_col[list_next[0]]) {

      r =  (hist_index             & get_red)   << shift_r;
      g = ((hist_index >> green_r) & get_green) << shift_g;
      b = ((hist_index >> blue_r)  & get_blue)  << shift_b;

      /* find first greater entry (break see init above) */
      i = 0;
      while (histogram[hist_index].n > list_num_col[list_next[i]]) i++;

      if (flag_euclid_min) {

        /* if option euclid. dist. min or optimization is set   */
        /* get the smallest eucl. dist. for all entries in list */
        for (j = 0, euclid_min_dist = 256*256*256; j < col_map_max; j++)
          if (list_num_col[list_next[j]] != 0) {
            euclid_tmp       = list_color_r[list_next[j]]  - r;
            euclid_mom_dist  = euclid_tmp * euclid_tmp;
            euclid_tmp       = list_color_g[list_next[j]]  - g;
            euclid_mom_dist += euclid_tmp * euclid_tmp;
            euclid_tmp       = list_color_b[list_next[j]]  - b;
            euclid_mom_dist += euclid_tmp * euclid_tmp;
            if (euclid_mom_dist < euclid_min_dist) {
              euclid_min_dist = euclid_mom_dist;
              k = j;
            }
        }

        if (euclid_min_dist > euclid_min) {
          /* take color in list */
          k = list_next[0];
          list_num_col[k] = histogram[hist_index].n;
          list_color_r[k] = r;
          list_color_g[k] = g;
          list_color_b[k] = b;
          for (l = 1; l < i; l++) list_next[l-1] = list_next[l];
          list_next[i-1] = k;
        }

        else {

        /* don't take color, but set number of representant */
        list_num_col[list_next[k]] = 
        list_num_col[list_next[k]] + histogram[hist_index].n;
        j = k + 1;

        /* so new sort is needed */
        while (list_num_col[list_next[k]] > list_num_col[list_next[j]]) j++;
          i = list_next[k];
          for (l = k + 1; l < j; l++) list_next[l-1] = list_next[l];
          list_next[j-1] = i;
        }
      }

      /* if no eucl. dist. min or optim. option is set */
      else {

        /* take color in list and sort list by number of colors */
        k = list_next[0];
        list_num_col[k] = histogram[hist_index].n;
        list_color_r[k] = r;
        list_color_g[k] = g;
        list_color_b[k] = b;
        for (l = 1; l < i; l++) list_next[l-1] = list_next[l];
        list_next[i-1] = k;
      }
  }

  if (flag_optimize) {

   for (i = col_map_max - 1, k = col_map_max; i > 0; i--)
   /* count the colors in colormap          */
   /* if (0,0,0) follows (0,0,0) (as init)  */
   /* then at least one of them is not used */

      if ( (list_color_r[list_next[i]] == 0) &&
           (list_color_g[list_next[i]] == 0) &&
           (list_color_b[list_next[i]] == 0) &&
           (list_color_r[list_next[i-1]] == 0) &&
           (list_color_g[list_next[i-1]] == 0) &&
           (list_color_b[list_next[i-1]] == 0))
           k--;

    fprintf (stderr,"Euclid. dist. min = ");
    fprintf (stderr,"%3d => %3d different colors in the colormap.\n",
             euclid_min / 3 ,k);

    /* I know goto is forbidden. But here it simplifies */
    /* the optimization algorithm                       */
    if ( (scan_direction == UP) && (k > col_map_max - 2) ) {
      euclid_min = (euclid_min / 3) + OPT_UP;
      goto TRYNEXT; /********************************************** GOTO used */
    }
    if ( (scan_direction == UP) && (k < col_map_max - 1) ) {
      scan_direction = DOWN;
      euclid_min = (euclid_min / 3) - OPT_DOWN;
      goto TRYNEXT; /********************************************** GOTO used */
    }
    if ( (scan_direction == DOWN) && (k < col_map_max - 1) ) {
      euclid_min = (euclid_min / 3) - OPT_DOWN;
      goto TRYNEXT; /********************************************** GOTO used */
    }
  }

  /* set colormap */
  /* sorted by number of colors! => faster mapping */
  for (i = col_map_max - 1; i > -1 ; i--) {
    red[col_map_max - 1 - i]   = list_color_r[list_next[i]];
    green[col_map_max - 1 - i] = list_color_g[list_next[i]];
    blue[col_map_max - 1 - i]  = list_color_b[list_next[i]];
  }

  /* reserve colors for sunview */
  if (flag_sunview) {
    red[254] = green[254] = blue[254] = 255;
    red[255] = green[255] = blue[255] = 0;
  }

  colormap.type   = RMT_EQUAL_RGB;
  colormap.length = 256;
  colormap.map[0] = red; colormap.map[1] = green; colormap.map[2] = blue;

  /* fix bug or undocumented function of pixrect functions */
  if ( (red[0] == 0) && (green[0] == 0) && (blue[0] == 0) ) blue[0] = 1;

  if ( (flag_prompt) && (!flag_optimize) ) fprintf (stderr,"done. \n");


  /* print different colors in colormap */

  for (i = 1, num_colors = col_map_max; i < col_map_max; i++)
    if ( (red[i] == 0) && (green[i] == 0) && (blue[i] == 0) &&
         (red[i-1] == 0) && (green[i-1] == 0) && (blue[i-1] == 0) ) 
      num_colors--;

  if ( (flag_prompt) && (!flag_optimize) ) {
    fprintf (stderr,"There are %d different colors in the colormap.\n",
    num_colors);
  }


/************************************************************ WRITE TO STDOUT */
  /* print histogram if option is set */
  if (flag_histogram)
    if (flag_stdout) {
      fprintf (stderr,"I write the image to stdout. ");
      fprintf (stderr,"So no other writing to stdout allowed! \n");
    }
    else {
      /* set registers for faster access */
      green_r =  8 - shift_r;
      blue_r  = 16 - shift_r - shift_g;


      printf ("Histogram for %s => %s\n",fn_in,fn_out);
      printf ("Number of colors : %d\n",num_colors);
        printf ("  red       green     blue       number of colors \n");
      for (i = 255; i > -1; i--) {

        r = list_color_r[list_next[i]];
        g = list_color_g[list_next[i]];
        b = list_color_b[list_next[i]];

        printf ("%3d..%3d  %3d..%3d  %3d..%3d        %4d \n",
                 r, r + (255 >> (8 - shift_r)),
                 g, g + (255 >> (8 - shift_g)),
                 b, b + (255 >> (8 - shift_b)),
                 list_num_col[list_next[i]]);
      }
  }


/************************************************************* MAPPING COLORS */
  if (!flag_floyd_steinb) {

    /* map colors to colormap */
    if (flag_prompt) fprintf (stderr,"Mapping colors ... ");

   /* init histogram as look up table for mapping */
   for (hist_index = 0; hist_index < hist_size;hist_index++)
      histogram[hist_index].n = -1;

    /* set registers for faster access */
    red_r   =      shift_r;
    green_r =      shift_g;
    blue_r  =      shift_b;
    green_l =  8 - shift_r;
    blue_l  = 16 - shift_r - shift_g;

    /* set image pointers to first pixel */
    im_ptr_in = (int *) mpr_d(mem_in)->md_image;
    im_ptr_8_out = (unsigned char *) mpr_d(mem_8_out)->md_image;

    /* loop over all pixels in x direction */
    for (i = 0; i < x*y; i++, im_ptr_in++, im_ptr_8_out++) {

      r =  (*im_ptr_in)        & 0xff;
      g = ((*im_ptr_in) >>  8) & 0xff;
      b = ((*im_ptr_in) >> 16) & 0xff;


      /* look for the coding in histogram */
      hist_index =  ( r >> red_r) +
                   (( g >> green_r) << green_l) +
                   (( b >> blue_r)  << blue_l);

      if (histogram [hist_index].n == -1) {

        /* if color is new then get the colormap color with the smallest */
        /* euclidean distance and put the colormap index in histogram */
        for (k = 0, euclid_min_dist = 256*256*256, color_index = 0;
             k < col_map_max; k++) {
          euclid_tmp       = r - red[k];
          euclid_mom_dist  = euclid_tmp * euclid_tmp;
          euclid_tmp       = g - green[k];
          euclid_mom_dist += euclid_tmp * euclid_tmp;
          euclid_tmp       = b - blue[k];
          euclid_mom_dist += euclid_tmp * euclid_tmp;
          if (euclid_mom_dist < euclid_min_dist) {
            color_index = k;
            euclid_min_dist = euclid_mom_dist;
          }
        }

        histogram[hist_index].n = color_index;
      }

      *im_ptr_8_out = histogram[hist_index].n;
    }
    if (flag_prompt) fprintf (stderr,"done. \n");
  }


  else {
/**************************************** MAPPING COLORS WITH FLOYD STEINBERG */
    /* map colors to colormap using floyd steinberg dithering */
    if (flag_prompt) {
      fprintf (stderr,"Error spreading : horizontal=");
      fprintf (stderr,"%d  diagonal=%d  vertical=%d  percent=%d\n",
               spread_hori, spread_diag, spread_vert,spread_percent);
      fprintf (stderr,"Mapping colors using Floyd Steinberg dithering ... ");
    }

    /* allocate memory for arrays holding scanline color errors */
    if ( (error_r = (int *) malloc ( (unsigned) x * sizeof (int))) == NULL) {
      fprintf (stderr,"\nError in malloc(). Not enough memory!\n");
      free ( (char *) histogram);
      free ( (char *) error_r);
      close_error (fp_in,fp_out,mem_in,mem_8_out);
      exit(1);
    }

    if ( (error_g = (int *) malloc ( (unsigned) x * sizeof (int))) == NULL) {
      fprintf (stderr,"\nError in malloc(). Not enough memory!\n");
      free ( (char *) histogram);
      free ( (char *) error_r);
      free ( (char *) error_g);
      close_error (fp_in,fp_out,mem_in,mem_8_out);
      exit(1);
    }

    if ( (error_b = (int *) malloc ( (unsigned) x * sizeof (int))) == NULL) {
      fprintf (stderr,"\nError in malloc(). Not enough memory!\n");
      free ( (char *) histogram);
      free ( (char *) error_r);
      free ( (char *) error_g);
      free ( (char *) error_b);
      close_error (fp_in,fp_out,mem_in,mem_8_out);
      exit(1);
    }

    /* initialize them */
    for (i = 0; i < x; i++) error_r[i] = error_g[i] = error_b[i] = 0;

    /* init histogram as look up table for mapping */
    for (hist_index = 0; hist_index < hist_size;hist_index++)
      histogram[hist_index].n = -1;

    /* set flag_percent for faster access */
    if (spread_percent == 100) flag_percent = FALSE; else flag_percent = TRUE;

    /* set registers for faster access */
    red_r   =  shift_r;
    green_r =  shift_g;
    blue_r  =  shift_b;
    green_l =  8 - shift_r;
    blue_l  = 16 - shift_r - shift_g;

    /* set image pointers to first pixel */
    im_ptr_in = (int *) mpr_d(mem_in)->md_image;
    im_ptr_8_out = (unsigned char *) mpr_d(mem_8_out)->md_image;

    /* for all scan lines */
    for (i = 0; i < y; i++) {

      /* initialize diagonal and horizontal errors */
      hori_err_r = hori_err_g = hori_err_b = 0;
      diag_err_r = diag_err_g = diag_err_b = 0;

      /* for all pixels in scan line */
      for (j = 0; j < x; j++, im_ptr_in++, im_ptr_8_out++) {

        /* get new colors and add errors */
        r = ( (*im_ptr_in)        & 0xff) + error_r[j] + hori_err_r;
        g = (((*im_ptr_in) >>  8) & 0xff) + error_g[j] + hori_err_g;
        b = (((*im_ptr_in) >> 16) & 0xff) + error_b[j] + hori_err_b;

        /* cut if under- or overflow */
        if (r < 0) r = 0; else if (r > 255) r = 255;
        if (g < 0) g = 0; else if (g > 255) g = 255;
        if (b < 0) b = 0; else if (b > 255) b = 255;

        hist_index =   (r >> red_r) +
                     ( (g >> green_r) << green_l) +
                     ( (b >> blue_r ) << blue_l );

        if (histogram [hist_index].n == -1) {

       /* if color is new then get the colormap color with the smallest */
        /* euclidean distance and put the colormap index in histogram */
          for (k = 0, euclid_min_dist = 256*256*256, color_index = 0; 
               k < col_map_max; k++) {
            euclid_tmp       = r - red[k];
            euclid_mom_dist  = euclid_tmp * euclid_tmp;
            euclid_tmp       = g - green[k];
            euclid_mom_dist += euclid_tmp * euclid_tmp;
            euclid_tmp       = b - blue[k];
            euclid_mom_dist += euclid_tmp * euclid_tmp;
            if (euclid_mom_dist < euclid_min_dist) {
              color_index = k;
              euclid_min_dist = euclid_mom_dist;
            }
          }
          histogram[hist_index].n = color_index;
        }

        *im_ptr_8_out = histogram[hist_index].n;

        /* set current errors */
        if (flag_percent) {
          curr_err_r = (int) (spread_percent * (r - red[*im_ptr_8_out]))  /
                                                                   hundred;
          curr_err_g = (int) (spread_percent * (g - green[*im_ptr_8_out])) /
                                                                   hundred;
          curr_err_b = (int) (spread_percent * (b - blue[*im_ptr_8_out])) /
                                                                   hundred;
        }
        else {
          curr_err_r = r - red[*im_ptr_8_out];
          curr_err_g = g - green[*im_ptr_8_out];
          curr_err_b = b - blue[*im_ptr_8_out];
        }

        /* spread error vertical */
        error_r[j] = diag_err_r + (curr_err_r * spread_vert) / hundred;
        error_g[j] = diag_err_g + (curr_err_g * spread_vert) / hundred;
        error_b[j] = diag_err_b + (curr_err_b * spread_vert) / hundred;

        /* spread error horizontal */
        hori_err_r =  (curr_err_r * spread_hori) / hundred;
        hori_err_g =  (curr_err_g * spread_hori) / hundred;
        hori_err_b =  (curr_err_b * spread_hori) / hundred;

        /* spread error diagonal */
        diag_err_r = (curr_err_r * spread_diag) / hundred;
        diag_err_g = (curr_err_g * spread_diag) / hundred;
        diag_err_b = (curr_err_b * spread_diag) / hundred;

      }
    }

    /* free memory for scan line errors */
    free ( (char *) error_r);
    free ( (char *) error_g);
    free ( (char *) error_b);

    if (flag_prompt) fprintf (stderr,"done. \n");
  }

  /* free memory used for histogram */
  free ( (char *) histogram);


/**************************************************************** WRITE IMAGE */
  /* write output image */
  if (put_image (fn_out,fp_in,fp_out,mem_in,mem_8_out,
      flag_prompt,colormap,out_format) != NULL) exit (1);


/************************************************************ WRITE TO STDOUT */
  /* write colormap to stdout if option is set */
  if (flag_write_map)
    if (flag_stdout) {
      fprintf (stderr,"I write the image to stdout. ");
      fprintf (stderr,"So no other writing to stdout allowed! \n");
    }
    else write_map (fn_out,red,green,blue);

  /* calculate euclidean distance if option is set */
  if (flag_euclid)
    if (flag_stdout) {
      fprintf (stderr,"I write the image to stdout. ");
      fprintf (stderr,"So no other writing to stdout allowed! \n");
    }
    else print_euclidean_dist
                     (fn_out,mem_in,mem_8_out,flag_prompt,red,green,blue,x,y);


/**************************************************************** ENDING MAIN */
  /* close files and free memory */
  close_success (fp_in,fp_out,mem_in,mem_8_out);

  /* null problemo */
  return (0);
}


/*******************************************************************************
 *   usage_exit                                                                *
 *                                                                             *
 *   Input  :                                                                  *
 *            - name      name of program as string                            *
 *                                                                             *
 *   Output :                                                                  *
 *            - writes the usage and the default values to stderr              *
 *                                                                             *
 *   Return : - exits with 1                                                   *
 *                                                                             *
 ******************************************************************************/
usage_exit (name)
char *name;
{
  fprintf (stderr,"\n%s V%s\n",name,VERSION);
  fprintf (stderr,"Usage: %s {options} <input filename> \n",name);
  fprintf (stderr,"               -o <output filename|%s> \n",
                                                               DEFAULT_STDOUT);
  fprintf (stderr,"               -en[+|-]        expand name with mode \n");
  fprintf (stderr,"               -ws[+|-]        write standard format \n");
  fprintf (stderr,"               -sv[+|-]        colors for sunview \n");
  fprintf (stderr,"               -sa <0..8>      shift all values in Bit \n");
  fprintf (stderr,"               -sr <0..8>      shift red values in Bit \n");
  fprintf (stderr,"               -sg <0..8>      shift green values in Bit\n");
  fprintf (stderr,"               -sb <0..8>      shift blue values in Bit \n");
  fprintf (stderr,"               -edm <0..%3d>   euclidean dist. minimum  \n",
                                                                    MAX_EUCLID);
  fprintf (stderr,"               -opt [0..%3d]   optimize colormap         \n",
                                                                    MAX_EUCLID);
  fprintf (stderr,"               -fs[+|-] [h d]  use Floyd Steinberg ");
  fprintf (stderr,"dither\n");
  fprintf (stderr,"                                 following parameters ");
  fprintf (stderr,"in %% :\n");
  fprintf (stderr,"                                 h = horizontal error ");
  fprintf (stderr,"spreading\n");
  fprintf (stderr,"                                 d = diagonal error ");
  fprintf (stderr,"spreading\n");
  fprintf (stderr,"                                 h, d are integers ");
  fprintf (stderr,"(h+d<=100)\n");
  fprintf (stderr,"               -fs%% <0..100>   percent for Floyd ");
  fprintf (stderr,"Steinberg \n");
  fprintf (stderr,"                               dithering \n");
  fprintf (stderr,"               -ce[+|-]        calculate euclid. ");
  fprintf (stderr,"distance\n");
  fprintf (stderr,"                               and write to stdout \n");
  fprintf (stderr,"               -hi             write histogram to stdout\n");
  fprintf (stderr,"               -m[+|-]         write colormap to stdout \n");
  fprintf (stderr,"               -p[+|-]         prompt info to stderr  \n");
  fprintf (stderr,"               -h              help (to stderr) \n");

  /* print the defaults */
  fprintf (stderr,"\nDefaults:                                       \n");
/* fprintf (stderr,"  - Extension of input file   : %s \n",DEFAULT_IN_EXT); */
  fprintf (stderr,"  - Extension of output file  : %s \n",DEFAULT_OUT_EXT);

  if (DEFAULT_EXP_NAM)
    fprintf (stderr,"  - Expand name               : + \n");
  else
    fprintf (stderr,"  - Expand name               : - \n");

  if (DEFAULT_OUT_FORM == RT_STANDARD)
    fprintf (stderr,"  - Write format              : standard \n");
  else
    fprintf (stderr,"  - Write format              : run length encoded \n");

  if (DEFAULT_SUNVIEW)
    fprintf (stderr,"  - Colors for sunview        : + \n");
  else
    fprintf (stderr,"  - Colors for sunview        : - \n");

  fprintf (stderr,"  - shift red values in Bit   : %d \n",DEFAULT_SHIFT_R);
  fprintf (stderr,"  - shift green values in Bit : %d \n",DEFAULT_SHIFT_G);
  fprintf (stderr,"  - shift blue values in Bit  : %d \n",DEFAULT_SHIFT_B);
  fprintf (stderr,"  - euclidean distance min    : %d \n",DEFAULT_EUCLID_MIN);

  if (DEFAULT_OPTIMIZE)
    fprintf (stderr,"  - Optimize colormap         : + \n");
  else
    fprintf (stderr,"  - Optimize colormap         : - \n");

  if (DEFAULT_FLOYD)
    fprintf (stderr,"  - Floyd Steinberg dither    : +  %d %d\n",
                        DEFAULT_SPREAD_HORI,DEFAULT_SPREAD_DIAG);
  else
    fprintf (stderr,"  - Floyd Steinberg dither    : -  %d %d\n",
                        DEFAULT_SPREAD_HORI,DEFAULT_SPREAD_DIAG);

  fprintf (stderr,"  - Percent for Floyd Steinb. : %d \n",
           DEFAULT_SPREAD_PERCENT);

  if (DEFAULT_EUCLID)
    fprintf (stderr,"  - Calculate euclidean dist. : + \n");
  else
    fprintf (stderr,"  - Calculate euclidean dist. : - \n");

  if (DEFAULT_HISTOGRAM)
    fprintf (stderr,"  - Write histogram to stdout : + \n");
  else
    fprintf (stderr,"  - Write histogram to stdout : - \n");


  if (DEFAULT_WRITE_MAP)
    fprintf (stderr,"  - Write colormap to stdout  : + \n");
  else
    fprintf (stderr,"  - Write colormap to stdout  : - \n");

  if (DEFAULT_PROMPT)
    fprintf (stderr,"  - Prompt info to stderr     : + \n");
  else
    fprintf (stderr,"  - Prompt info to stderr     : - \n");

  fprintf (stderr,"\n-> try %s |& more \n",name);

  exit(1);
}


/*******************************************************************************
 *   help_exit                                                                 *
 *                                                                             *
 *   Input  :                                                                  *
 *            - name      name of program as string                            *
 *                                                                             *
 *   Output : - writes the help to stderr                                      *
 *                                                                             *
 *   Return : - exits with 1                                                   *
 *                                                                             *
 ******************************************************************************/
help_exit (name)
char *name;

{
  fprintf (stderr,"Help for %s V%s \n",name,VERSION);
  fprintf (stderr," I convert 24 or 32 Bit pixrect or rayshade images\n");
  fprintf (stderr," to 8 Bit colormapped images for suns using the\n");
  fprintf (stderr," popularity algorithm. Here are some valid examples\n");
  fprintf (stderr," for calling:\n");
  fprintf (stderr,"   %s -sa 2 -en- -p hsv.pixrect\n",name);
  fprintf (stderr,"   %s -sv -o %s tree.pic | rastool \n",name,DEFAULT_STDOUT);
  fprintf (stderr,"   %s -fs -o test.pic_8 test.pic_32 \n",name);
  fprintf (stderr,"   %s -fs -fs%% 75 -sv hsv\n",name);
  fprintf (stderr,"   %s -sa 3 -sr 2 -edm 75 hsv.pixrect\n",name);
  fprintf (stderr,"   %s -sa 3 -opt plant.pic\n",name);
  exit (1);
}
