/* program to display image and/or histogram etc stored in log file

to run, type:

landd [-x<file size> -n<new image> -d( no dither )
                                             <intensity file> <log file>] 

*/

#include <graph.h>
#include <stdio.h>
#include <signal.h>
#include "az:plane.h"
#include "az:general.h"

#define Y_BASE  75             /* baseline for image and histogram */
#define X_SIDE  50             /* left side of disp. square */


char menu_flag;      /* true if main menu active */
char move_flag;      /* true if text line cleared when cursor moved */
char hist_flag;      /* true if histogram required */
char int_flag;       /* if true intensity sampled, else lightness sampled */
char both_flag;      /* if true intensity and lightness sampled */
char dith_flag;      /* true if dither required */
char larg_flag;      /* true if expanded display required */

char new_flag;       /* true if new image displayed */

unsigned short fontbuf[FONTSIZE];	/* buffer for largest expected font */
char *fontname = "fmacs:font.visual";
int l, h, w;

int grey;               /* current grey level for text & information regions */


FILE *fp, *flog;

int size_file = 0;            /* size of file */
int size = 0;                 /* size of image */
int scale_size = 1;      /* enlargement factor for displaying image, reduction
                            factor when writing out image */

char int_array[ 256 * 256 ];  /* intensity array */

int xl_int;            /* x of origin for intensity histogram */
int xl_lig;            /* x of origin for lightness histogram */
int xr_int;            /* x for end of intensity histogram x axis */
int xr_lig;            /* x for end of lightness histogram x axis */
int x_bar_int;         /* x position of intensity histogram bar */
int x_bar_lig;         /* x position of lightness histogram bar */
int hist_space;        /* spacing between histogram axes and bar */


void draw_cursor(), clear_cursor(), plot_curs();
void region(), read_info(), draw_all();


void setup_hist(), draw_hist(), draw_bar(), redraw_bars(), reset(),clear_hist();
extern stop();


main(argc,argv)
char **argv;
int argc;
{
   char header_flag = TRUE; /* true if file contains header */
   char arg_flag = FALSE;   /* true if command line arguments given */
   char c;


   signal( SIGINT, stop );

   dith_flag = TRUE;         /* FLAG DEFAULTS */
   larg_flag = FALSE;

   new_flag = FALSE;

   if ( argc > 1 ) { /* command line arguments given */
      argv++;
      arg_flag = TRUE;

      while( ( argc > 0 ) && ( (*argv)[0] == '-' ) )
      {
         switch( (*argv)[1] ) {

            case 'x':
               sscanf( *argv + 2, "%d", &size_file);
               header_flag = FALSE;
               break;

            case 'd':      /* no dither */
               dith_flag = FALSE;
               break;

            case 'n': 
               new_flag = TRUE;
               break;

            default:
               error( "bad option");
               break;
         } 
  
         argc--;
         argv++;
      }               
   }       

   /* check correct number of files */

   --argc;

   if ( ( new_flag && ( argc != 2 ) ) || ( !new_flag && argc != 1 ) )
   {
      putchar( BEEP );
      error( "incorrect number of files given" );
   }

   l = readfont(fontname, fontbuf, FONTSIZE, &h, &w);

   grey = P_WHITE;

   offset(0,0);
   sterm( 5 );

   if ( new_flag )
   {
      setup_map();
      clear_screen();
      setup_text();
   }


   hist_flag = TRUE;          /*   DEFAULT VALUES  */
   int_flag = FALSE;
   menu_flag = FALSE;  
   both_flag = TRUE;

   setup_hist();

   if ( new_flag ) /* open and display intensity file */
   {
      if ( ( fp = fopen( *(argv++), "r" ) ) == NULL )
      {
         putchar( BEEP );
         error( "can't open picture file" );
      }
      else      /* read and display intensity file */
      {
         if ( header_flag )
            size_file = getc( fp ) & 0377;
       
            display( X_SIDE, Y_BASE, int_array, FALSE );
      }

      clear_text();   
   }

   /* open log file */

   if ( ( flog = fopen( *argv, "r" ) ) == NULL )
      error("can't open log file");

   region();

}


void region() /*  middle Mouse Button ( MB ) selects option */
{
   char text[30];
   int n, i;

   int xb = 325;
   int yb = Y_BASE + 200;
   int int_b = 0;      /* intensity at cyam cursor */
   int lig_b = 0;      /* lightness at cyam cursor */

   int xr = 325;
   int yr = Y_BASE + 100;
   int int_r = 0;      /* intensity at red cursor */
   int lig_r = 0;      /* lightness at red cursor */

   if ( new_flag )
      draw_hist();

   read_info( &xb, &yb, &int_b, &lig_b, &xr, &yr, &int_r, &lig_r );
   draw_all( xb, yb, int_b, lig_b, xr, yr, int_r, lig_r );
}

      
         
void read_info( pxb, pyb, pint_b, plig_b, pxr, pyr, pint_r, plig_r ) /* reads
                                   in variables from file */
int *pxb, *pyb, *pint_b, *plig_b, *pxr, *pyr, *pint_r, *plig_r;
{
         fscanf( flog, "%d   %d   %d   %d", pxb, pyb, pint_b, plig_b);
         fscanf( flog, "%d   %d   %d   %d", pxr, pyr, pint_r, plig_r);
}

void draw_all( xb, yb, int_b, lig_b, 
               xr, yr, int_r, lig_r ) /* clears old cursors and bars and 
                                         redraws with new */
int xb, yb, int_b, lig_b, xr, yr, int_r, lig_r;
{
     /* clear RED & CYAM from previous histogram etc */

     if ( !new_flag )
     {
        enable( P_COL );
        colour( BLACK );
        fill( 0, 0, XPIXELS, YPIXELS );
     }

      enable( P_CYAM );

      draw_cursor( xb, yb);

      int_flag = TRUE;
      x_bar_int = xl_int + hist_space;
      draw_bar( int_b, 0 );

      int_flag = FALSE;
      x_bar_lig = xl_lig + hist_space;
      draw_bar( lig_b, 0 );

      enable( P_RED );

      draw_cursor( xr, yr);

      int_flag = TRUE;
      x_bar_int = xl_int + hist_space + 50;
      draw_bar( int_r, 0 );

      int_flag = FALSE;
      x_bar_lig = xl_lig + hist_space + 55;
      draw_bar( lig_r, 0 );
}                                          


void draw_cursor( x, y) /* draws cursor */
int x, y;
{
   colour( P_COL );
   plot_curs( x, y);
}

void clear_cursor( x, y) /* clears cursor */
int x, y;
{
   colour( BLACK );
   plot_curs( x, y);
}



void plot_curs( x, y) /* draws cursor shape */
int x, y;
{
int i;

   /* vertical lines */

   line( x, y - 11, x, y - 4 );
   line( x, y + 4, x, y + 11 );

   /* horizontal lines */

   hline( x - 11, x - 4, y );
   hline( x + 4, x + 11, y );
}

/* ********************** HISTOGRAM FUNCTIONS ***************************** */

void setup_hist() /* initialises variables for drawing histograms and bars */
{
   if ( !both_flag ) {                           
      xl_int = xl_lig = 450;
      xr_int = xr_lig = 600;
      hist_space = 50;
   }
   else {
      xl_int = 420;
      xr_int = 510;
      xl_lig = 590;
      xr_lig = 680;
      hist_space = 15;
   }
}

void draw_hist() /* draws axes for histogram */
{
   float scale_factor, y_scaled, y_print;
   int x_left, x_right, x_Yaxis;
   int y_Xaxis, x_text;
   int y_bottom, y_top, y; 
   int y_int;
   char text_switch, *text;

   static int tick = 7;
   static int y_delta = 6;
   static char space[ 20 ] = ""; /* space to store text */

   /* clear space */
   clear_hist();

   enable(P_GREY);
   colour( DIM );

   if ( int_flag || both_flag ) { /* draw axes for intensity histogram
                                                              0 <= y <= 255 */
      x_left = xl_int;
      x_right = xr_int;

      x_Yaxis = xl_int;
      y_Xaxis = Y_BASE;
      y_bottom = y_Xaxis;
      y_top = 260 + y_bottom;

      x_text = x_left - 40;

      /* draw axes */
      hline( x_left, x_right, y_Xaxis);
      line( x_Yaxis, y_bottom, x_Yaxis, y_top);
 
      /* draw ticks and text */

      for( y = 0; y < 261; y += 32) {
      
         hline( x_Yaxis, x_Yaxis - tick, y + y_Xaxis); /* draw tick */
         setpos( x_text, y + y_Xaxis - y_delta);
         text = space;

         if ( y < 10 ) 
            sprintf( text, "  %d", y);
         else {
 
            if ( y < 100 )
               sprintf( text, " %d", y);
            else
               sprintf( text, "%d", y);
            }

         while (*text) gputc(*text++); /* write text */
      } 

      /* label histogram */

      setpos( xl_int + hist_space - w, Y_BASE - 40 );
      text = "intensity"; 
      while (*text) gputc(*text++); /* write text */
   }

   if ( !int_flag || both_flag ) { 

   /* draw axes for lightness histogram  -128 < y < 128 */
   
      x_left = xl_lig;
      x_right = xr_lig;

      x_Yaxis = xl_lig;
      y_Xaxis = Y_BASE + 128;
      y_bottom = y_Xaxis - 140;
      y_top = y_Xaxis + 140;

      x_text = xl_lig - 40 - 2 * w; /* extra space for "-" sign & 0 */

      /* draw axes */
      hline( x_left, x_right, y_Xaxis);
      line( x_Yaxis, y_bottom, x_Yaxis, y_top);
 
      /* draw ticks and text */

      text_switch = TRUE;
      scale_factor = 1.28 / 1.20412;  /* half scale = log10( 16 ) = 1.20412 */

      for( y = -125; y < 126; y += 25 ) {

         text_switch = !text_switch; 

         y_scaled = y * scale_factor;    /* y position on axis  */
         if ( y > 0 )
            y_int = ( y_scaled + 0.5 );
         else
            y_int = ( y_scaled - 0.5 );

         hline( x_Yaxis, x_Yaxis - tick, y_int + y_Xaxis); /* draw tick */

         if ( text_switch ) { /* write text */
            y_print = y / 100.0;
            setpos( x_text, y_int + y_Xaxis - y_delta);
            text = space;

            if ( y >= 0 )
               sprintf( text, " %.2f", y_print );
            else
               sprintf( text, "%.2f", y_print );

            while (*text) gputc(*text++); /* write text */
         }
      } 

      /* label histogram */

      setpos( xl_lig + hist_space - w, Y_BASE - 40 );
      text = "lightness"; 
      while (*text) gputc(*text++); /* write text */
   }
}
   
void draw_bar( ht, old_ht ) /* draws bar of height ht at global x_bar */
                       /* 2 cases : if int_flag TRUE 
                                       prints height below ; for 0 <= ht <= 255 
                                    else
                                       no text & for -128 < ht < 128 */
int ht, old_ht;
{
   static float scale_factor = 1.20412 / 128; /* half scale = 1.20412 */
   float 
   ht_scaled;
   int x_bar;        /* left side of bar */
   int y_axis;       /* bottom of bar */
   int x_text;       /* text x position */
   char *text;

   static int width = 10;              /* width of bar */ 
   static char space[ 10 ] = "";       /* space to store text */
   static char space_lig[ 10 ] = "";   /* space for lightness text */
   static int y_text = Y_BASE - 20;    /* text y position */

   if ( ht != old_ht) {

      if ( int_flag ) { /* draws bar & prints text for 0 <= ht <= 255 */

         x_bar = x_bar_int;
         y_axis = Y_BASE;
         x_text = x_bar -  w;

         /* change text */  

         text = space;
         colour(P_BLACK);
         setpos( x_text, y_text );
         while (*text) gputc(*text++); /* erase old text */

         text = space;
         if ( ht < 10 ) 
            sprintf( text, "  %d", ht);
         else if ( ht < 100 )
            sprintf( text, " %d", ht);
         else
            sprintf( text, "%d", ht);

         colour(P_COL);
         setpos( x_text, y_text );
         text = space;
         while (*text) gputc(*text++); /* write new text */

         /* change bar height */

         if ( ht > old_ht ) {
            colour(P_COL);
            fill( x_bar, old_ht + y_axis,
                  x_bar + width, ht + y_axis);
         }
         else {
            colour(P_BLACK);
            fill( x_bar, ht + y_axis,
                  x_bar + width, old_ht + y_axis);
         }
      }

      else { /* draw bar for -128 < ht < 128 */

         x_bar = x_bar_lig;
         y_axis = Y_BASE + 128;
         x_text = x_bar - 18; /* 2 * w */

         /* clear old text */

         colour( BLACK );
         fill( x_text, y_text, x_text + 45, y_text + 11 );

         /* write new text */

         colour(P_COL);
         setpos( x_text, y_text );
         text = space_lig;
         ht_scaled = ht * scale_factor;
         if ( ht >= 0 )
            sprintf( text, " %.2f", ht_scaled );
         else
            sprintf( text, "%.2f", ht_scaled );

         while (*text) gputc(*text++); /* write text */

         /* change bar height */

         if ( ( ht > 0 ) && ( old_ht > 0 ) )
            if ( ht > old_ht ) {
               colour(P_COL);
               fill( x_bar, old_ht + y_axis,
                     x_bar + width, ht + y_axis);
            }
            else {
               colour(P_BLACK);
               fill( x_bar, ht + y_axis,
                     x_bar + width, old_ht + y_axis);
            }

         else if ( ( ht > 0 ) && ( old_ht > 0 ) )
            if ( ht > old_ht ) {
               colour(P_BLACK);
               fill( x_bar, old_ht + y_axis,
                     x_bar + width, ht + y_axis);
            }
            else {
               colour(P_COL);
               fill( x_bar, ht + y_axis,
                     x_bar + width, old_ht + y_axis);
            }
         else { /* ht & old_ht have opposite signs or one is zero */
            colour(P_BLACK);
            fill( x_bar, old_ht + y_axis,
                  x_bar + width, y_axis);
            colour(P_COL);
            fill( x_bar, ht + y_axis,
                  x_bar + width, y_axis);
         }   
      }
   }
}

void clear_hist() /* clears histogram region */
{
   int xl, xr;

   static int base = Y_BASE - 40;
   static int top = Y_BASE + 270;

   enable(P_ALL);
   colour(BLACK);

   xl = 420 - 40 - 2 * w;
   xr = XPIXELS;
   fill( xl, base, xr, top);
}

stop()
{
   fclose( flog );
   exit( 1 );
}

