/**************************************************
*  file d:\cips\ht.c
*
*  Purpose: This program displays an image using a
*  half toning process.  The algorithm was taken
*  from "Personal computer based image processing
*  with halftoning," John A Saghri, Hsieh S. Hou,
*  Andrew Tescher, Optical Engineering, March 1986,
*  Vol.25, No. 3, pp 499-503. The
*  display_using_halftoning determines display
*  size and reads the image. The half_tone function
*  implements the algorithm.
*         
*  The function print_halftone_array prints a half
*  toned image array to a regular line printer.
*
*  External Calls:
*     rtiff.c - read_tiff_image (March CUJ, Lising 3)
*     rstring.c - read_string
*     numcvrt.c - get_integer
*
*   Modifications:
*       30 September 86 - created
*       18 August 1990 - modified for use in the
*         C Image Processing System.
**************************************************/


#include "d:\cips\cips.h"

#define  FORMFEED  '\014'

float eg[ROWS][COLS], ep[ROWS][COLS];

display_using_halftoning(in_image, file_name,
    il, ie, ll, le, threshold, invert,
    image_colors, image_header, monitor_type,
    print)

   char  file_name[], monitor_type[];
   int   image_colors, invert,
         il, ie, ll, le, threshold,
         print;
   short in_image[ROWS][COLS];
   struct tiff_header_struct *image_header;

{
   char response[80];

   int  channel,
        color,
        display_mode,
        horizontal,
        i,
        j,
        k,
        l,
        max_horizontal,
        max_vertical,
        not_finished,
        one,
        vertical,
        x,
        y,
        zero;

/*******************************************
*   Use the monitor type to set the vertical
*   horizontal and display_mode parameters.
*   Also set the values for one and zero.
*   one and zero will vary depending on the
*   monitor type.
********************************************/

    if(  (monitor_type[0] == 'M')  ||
         (monitor_type[0] == 'm')){
       vertical     = 3;
       horizontal   = 2;
       display_mode = _HRESBW;
       one          = 1;
       zero         = 0;
    }

    if(  (monitor_type[0] == 'C')  ||
         (monitor_type[0] == 'c')){
       vertical     = 3;
       horizontal   = 2;
       display_mode = _MRES4COLOR;
       one          = 3;
       zero         = 1;
    }
    if(  (monitor_type[0] == 'V')  ||
         (monitor_type[0] == 'v')){
       vertical     = 6;
       horizontal   = 4;
       display_mode = _VRES16COLOR;
       one          = 15;
       zero         = 1;
    }

    if(  (monitor_type[0] == 'E')  ||
         (monitor_type[0] == 'e')){
       vertical     = 6;
       horizontal   = 3;
       display_mode = _ERESCOLOR;
       one          = 15;
       zero         = 1;
    }

    max_horizontal = (image_header->image_length+
                      50)/100;
    max_vertical   = (image_header->image_width+
                      50)/100;

    if(horizontal > max_horizontal) horizontal = 
                          max_horizontal;
    if(vertical > max_vertical) vertical = 
                          max_vertical;

    if(print == 1){
       vertical   = 1;
       horizontal = 1;
    }

      /* set graphics mode */
    if(print == 0)
       _setvideomode(display_mode); /* MSC 6.0 */
    else{
       printf("\n\nHT> Calculating for printing ");
       printf("\nHT> Counting from 0 to 99\n");
    }

/*********************************************
*   Loop over horizontal and vertical. Read
*   the image array and display it after
*   calculating the half tone values.
*********************************************/

    for(i=0; i<horizontal; i++){
       for(j=0; j<vertical; j++){
          read_tiff_image(file_name, in_image, 
                         il+i*100, ie+j*100, 
                         ll+i*100, le+j*100);
          half_tone(in_image, threshold, eg, ep, 
                    i, j, one, zero, invert, 
                    print);
       }
    }
 
    if(print == 1) printf("\n\nHT> Hit ENTER \
to continue");
    read_string(response);
    clear_text_screen();

}  


/*******************************************
*   half_tone(...
*
*   ep[m][n] = sum of erros propogated
*               to position (m,n).
*   eg[m][n] = total error generated at
*               location (m,n).
********************************************/

half_tone(in_image, threshold, eg, ep, yoff,
         xoff, one, zero, invert, print)
   int   invert, threshold, xoff, yoff,
         one, print, zero;
   float eg[ROWS][COLS], ep[ROWS][COLS];
   short in_image[ROWS][COLS];
{
   float c[2][3],
         sum_p,
         t,
         tt;
   int   color, count, i, j, m, n;
   short srow, scol;

   c[0][0] = 0.0;
   c[0][1] = 0.2;
   c[0][2] = 0.0;
   c[1][0] = 0.6;
   c[1][1] = 0.1;
   c[1][2] = 0.1;
   count   =   0;

/***********************************************
*   Calculate the total propogated error
*   at location(m,n) due to prior
*   assignment.
*
*   Go through the input image.  If the output
*   should be one then display that pixel as such.
*   If the output should be zero then display it
*   that way.
*
*   Also set the pixels in the input image array
*   to 1's and 0's in case the print option
*   was chosen.
************************************************/

   for(i=0; i<ROWS; i++){
      for(j=0; j<COLS; j++){
         eg[i][j] = 0.0;
         ep[i][j] = 0.0;
      }
   }

/**********************************************
*   29 February 1988 - Fix to remove a solid 
*   line at the bottom of each region. Loop over 
*   ROWS-1 and then draw an extra line.
***********************************************/

   for(m=0; m<ROWS-1; m++){
      for(n=0; n<COLS; n++){

         sum_p = 0.0;
         for(i=0; i<2; i++){
            for(j=0; j<3; j++){
               sum_p = sum_p + c[i][j] * 
                       eg[m-i+1][n-j+1];
            }  /* ends loop over j */
         }     /* ends loop over i */

         ep[m][n] = sum_p;
         t = in_image[m][n] + ep[m][n];
         tt = t;

    /**********************************
    *    Here set the point [m][n]=one
    ***********************************/

         if(t > threshold){
            eg[m][n] = t - threshold*2;
            ++count;
            color = one;
            if(invert == 1) color = zero;
    
            scol = (short)(n + xoff*COLS);
            srow = (short)(m + yoff*ROWS);

            if(invert == 1)
               in_image[m][n] = 1;
            else
               in_image[m][n] = 0;

            if(print == 0){
               _setcolor(color);      /* MSC 6.0 */
               _setpixel(scol, srow); /* MSC 6.0 */
            }  /* ends if print == 0 */
         }  /* ends if t > threshold  */

     /**********************************
     *    Here set the point [m][n]=zero
     ***********************************/

         else{
            eg[m][n] = t;
            color = zero;
            if(invert == 1) color = one;
      
            scol = (short)(n + xoff*COLS);
            srow = (short)(m + yoff*ROWS);

            if(invert == 1)
               in_image[m][n] = 0;
            else
               in_image[m][n] = 1;

            if(print == 0){
               _setcolor(color);      /* MSC 6.0 */
               _setpixel(scol, srow); /* MSC 6.0 */
            } /* ends if print == 0 */
         }  /* ends else t <= threshold  */
      }  /* ends loop over n columns */

      if(print == 1) printf("%3d", m);
   }         /* ends loop over m rows */

 /* Now display an extra line if print is 0 */
   if(print == 0){
      for(j=0; j<COLS; j++){

        if(in_image[ROWS-2][j] == 1)
           color = zero;
        else
           color = one;

        if(invert == 1){
            if(in_image[ROWS-2][j] == 1)
               color = zero;
            else
               color = one;
        }  /* ends if invert == 1 */

        scol = (short)(j + xoff*COLS);
        srow = (short)(ROWS-1 + yoff*ROWS);
        _setcolor(color);      /* MSC 6.0 */
        _setpixel(scol, srow); /* MSC 6.0 */

      }        /* ends loop over j */
   }        /* ends if print == 0 */


   if(print == 1) print_halftone_array(in_image);

}  /*  ends half_tone  */

 /*******************************
 *   get_threshold_value(...
 ********************************/

get_threshold_value(threshold, print)
   int *print, *threshold;
{
   int i;
   printf("\nHT> The threshold = %d", *threshold);
   printf("\nHT> Enter new theshold value ");
   printf("(0 for no change) \n___\b\b\b");
   get_integer(&i);
   if((i != 0) && (i!= *threshold))
       *threshold = i;

   printf("\nHT> print = %d (1 for print  0 for \
display)", *print);
   printf("\nHT> Enter print value  \n_\b");
   get_integer(&i);
   *print = i;
}

/********************************************
*   print_halftone_array(...
*
*   This function takes the halftoned images
*   and prints it to a line printer.  If the
*   image array has a 1 then print a ' '.
*   If the image array has a 0 then print
*   a '*'.
*********************************************/

print_halftone_array(image)
   short image[ROWS][COLS];
{
   char printer_name[80], response[80], string[101];
   FILE *printer;
   int   i, j, l, line_counter;

   line_counter = 0;

   strcpy(printer_name, "prn");

   if( (printer = fopen(printer_name, "w")) == NULL)
      printf("\nHT> Could not open printer");
   else{
      printf("\nOpened printer and now printing");

/***************************************************
*   Loop over the rows in the image.  For each row
*   first clear out the string print buffer.
*   Then go through the columns and set the string
*   to either '*' or ' '.  Finally, write the 
*   string out to the printer.
***************************************************/

       for(i=0; i<ROWS; i++){
          for(l=0; l<COLS+1; l++) string[l] = '\0';
    
          for(j=0; j<COLS; j++){
             if(image[i][j] == 1)
                string[j] = '*';
             else
                string[j] = ' ';
          }  /* ends loop over j columns */
    
          printf("%3d", i);
          my_fwriteln(printer, string);
          line_counter = line_counter + 1;
          if(line_counter >= 53){
             line_counter = 0;
             putc(FORMFEED, printer);
          }  /* ends if line_counter >=53  */
    
       }  /* ends loop over i rows */
    
   }  /* ends opened printer */

   putc(FORMFEED, printer);
   fclose(printer);

}  /* ends print_halftone_array */
