home *** CD-ROM | disk | FTP | other *** search
/ Encyclopedia of Graphics File Formats Companion / GFF_CD.ISO / software / unix / saoimage / sao1_07.tar / sclctrl.c < prev    next >
C/C++ Source or Header  |  1991-06-21  |  10KB  |  312 lines

  1. #ifndef lint
  2. static char SccsId[] = "%W%  %G%";
  3. #endif
  4.  
  5. /* Module:    sclctrl.c (Scale Control)
  6.  * Purpose:    Construct the image-to-display map
  7.  * Subroutine:    select_scalemap()        returns: void
  8.  * Subroutine:    new_scalemap()            returns: void
  9.  * Copyright:    1989 Smithsonian Astrophysical Observatory
  10.  *        You may do anything you like with this file except remove
  11.  *        this copyright.  The Smithsonian Astrophysical Observatory
  12.  *        makes no representations about the suitability of this
  13.  *        software for any purpose.  It is provided "as is" without
  14.  *        express or implied warranty.
  15.  * Modified:    {0} Michael VanHilst    initial version          30 May 1989
  16.  *        {1} MVH enable setting one limit w/o other   24 November 1989
  17.  *        {2} MVH use full area for small image histogram  19 June 1991
  18.  *        {n} <who> -- <does what> -- <when>
  19.  */
  20.  
  21. #include <stdio.h>        /* get stderr */
  22. #include <X11/Xlib.h>        /* X window stuff */
  23. #include <X11/Xutil.h>        /* X window manager stuff */
  24. #include "hfiles/constant.h"    /* define codes  */
  25. #include "hfiles/define.h"    /* define MIN, MAX, DONT_CARE, etc. */
  26. #include "hfiles/struct.h"    /* declare structure types */
  27. #include "hfiles/extern.h"    /* extern main parameter structures */
  28. #include "hfiles/scale.h"    /* define scaling constants */
  29.  
  30. #ifdef ANSIC
  31. static void new_histogram();
  32. static void get_histlims ( int *histogram, int *pmin, int *pmax );
  33. static int get_histogram_total ( int *histogram, int pmin, int pmax );
  34. static void make_histogram ( short *shortbuf, int *histogram, int ncols,
  35.                  int x, y, width, height, int *area );
  36. #else
  37. static void new_histogram();
  38. static void get_histlims();
  39. static int get_histogram_total();
  40. static void make_histogram();
  41. #endif
  42.  
  43. /*
  44.  * Subroutine:    select_scalemap
  45.  * Purpose:    Respond to input from the scale menu (mostly rescaling)
  46.  */
  47. void select_scalemap ()
  48. {
  49.   void new_scalemap(), save_blink();
  50.   void map_panbox(), disp_panbox(), map_dispbox(), disp_dispbox();
  51.  
  52.   if( (control.response[0] == SOP) && (control.response[1] != 0) ) {
  53.     if( control.response[1] == SOP_Blink ) {
  54.       save_blink((int)control.event.xbutton.button);
  55.     } else {
  56.       color.scale.mode = control.response[1];
  57.       /* make the new lookup table */
  58.       new_scalemap();
  59.       /* refill display buffers with rescaled values and display */
  60.       map_panbox();
  61.       disp_panbox();
  62.       /* panbox first because it is faster */
  63.       map_dispbox();
  64.       disp_dispbox();
  65.     }
  66.   }
  67. }
  68.  
  69. /*
  70.  * Subroutine:    new_scalemap
  71.  * Purpose:    Scalemap calculation for a new image
  72.  */
  73. void new_scalemap ( )
  74. {
  75.   static double cmdMin = 0.0;
  76.   static double cmdMax = 0.0;
  77.   static int min_given = 0;    /* stored values to detect change */
  78.   static int max_given = 0;
  79.   static int imtool_200 = 0;
  80.   static int init = 1;        /* identify first time called */
  81.   static void new_histogram();
  82.   void make_scalemap(), color_logo();
  83. #ifdef IMTOOL
  84.   void set_imtool_colors();
  85. #endif
  86.  
  87.   /* if the image has been changed, recompute min, max, and histogram */
  88.   if( (buffer.mm.img_leftX != coord.id.srcX1) ||
  89.       (buffer.mm.img_topY != coord.id.srcY1) ||
  90.       (buffer.mm.img_rightX != coord.id.srcX2) ||
  91.       (buffer.mm.img_lowY != coord.id.srcY2) ||
  92.       (img.imtool_200 != imtool_200) ||
  93.       (min_given != buffer.min_given) || (cmdMin != buffer.cmdMin) ||
  94.       (max_given != buffer.max_given) || (cmdMax != buffer.cmdMax) ) {
  95.     new_histogram();
  96.     min_given = buffer.min_given;
  97.     max_given = buffer.max_given;
  98.     cmdMin = buffer.cmdMin;
  99.     cmdMax = buffer.cmdMax;
  100.     imtool_200 = img.imtool_200;
  101.   }
  102.   /* make the scale map */
  103.   if( color.ncolors == 1 ) {
  104.     color.ncolors = 256;
  105.     make_scalemap(buffer.scale_min, buffer.scale_max);
  106.     color.ncolors = 1;
  107.   } else {
  108.     make_scalemap(buffer.scale_min, buffer.scale_max);
  109.     /* if this is imtool, map its graphics image levels */
  110.     if( init && (img.file_type == SOP_Logo) )
  111.       color_logo(buffer.scalemap + SCALEOFF,
  112.          color.hard.blue, color.hard.yellow);
  113. #ifdef IMTOOL
  114.     else if( img.imtool_200 )
  115.       set_imtool_colors();
  116. #endif
  117.     init = 0;
  118.   }
  119. }
  120.  
  121. /*
  122.  * Subroutine:    new_histogram
  123.  * Purpose:    Do all coordinate stuff surrounding histogram calculation
  124.  *        and call make_histogram
  125.  */
  126. static void new_histogram ( )
  127. {
  128.   float X1, Y1, X2, Y2;
  129.   void i_transform();
  130.  
  131.   /* calculate min, max, and histogram but not completely to the edges */
  132.   if( (coord.buf.Xwdth > 32) && (coord.buf.Yhght > 32) ) {
  133.     if( control.verbose )
  134.       (void)printf("Assessment of window display (in 1 from edges):\n");
  135.     i_transform(&coord.imgtobuf,
  136.         coord.id.srcX1 + 1, coord.id.srcY1 + 1, &X1, &Y1);
  137.     i_transform(&coord.imgtobuf,
  138.         coord.id.srcX2 - 1, coord.id.srcY2 - 1, &X2, &Y2);
  139.   } else {
  140.     if( control.verbose )
  141.       (void)printf("Assessment of window display:\n");
  142.     i_transform(&coord.imgtobuf, coord.id.srcX1, coord.id.srcY1, &X1, &Y1);
  143.     i_transform(&coord.imgtobuf, coord.id.srcX2, coord.id.srcY2, &X2, &Y2);
  144.   }
  145.   make_histogram(buffer.shortbuf, buffer.histogram, coord.buf.width,
  146.          (int)X1, (int)Y1, 1+(int)X2-(int)X1, 1+(int)Y2-(int)Y1,
  147.          &buffer.hist_area);
  148.   get_histlims(buffer.histogram, &buffer.scale_min, &buffer.scale_max);
  149.   if( control.verbose ) {
  150.     if( img.fiscaled == 0 ) {
  151.       (void)printf("Pixel minimum = %d, pixel maximum = %d\n",
  152.            buffer.scale_min, buffer.scale_max);
  153.     } else {
  154.       float fmin, fmax;
  155.       fmin = (buffer.scale_min * img.fiscale) + img.fibias;
  156.       fmax = (buffer.scale_max * img.fiscale) + img.fibias;
  157.       (void)printf("Pixel minimum = %g, pixel maximum = %g\n", fmin, fmax);
  158. #ifdef DEBUG
  159.       (void)printf("(unscaled - min: %d, max: %d)\n",
  160.            buffer.scale_min, buffer.scale_max);
  161. #endif
  162.     }
  163.   }
  164.   /* store info about this calculation for future reference */
  165.   buffer.mm.img_leftX = coord.id.srcX1;
  166.   buffer.mm.img_topY = coord.id.srcY1;
  167.   buffer.mm.img_rightX = coord.id.srcX2;
  168.   buffer.mm.img_lowY = coord.id.srcY2;
  169.   buffer.scalemap_summing = buffer.shortbuf_summing;
  170.   /* allow command line limit override */
  171.   if( buffer.min_given || buffer.max_given ) {
  172.     int histmin, histmax;
  173.     if( buffer.min_given ) {
  174.       if( img.fiscaled )
  175.     buffer.cmdmin = (buffer.cmdMin - img.fibias) / img.fiscale;
  176.       else
  177.     buffer.cmdmin = buffer.cmdMin;
  178.       histmin = MAX(buffer.cmdmin, buffer.scale_min);
  179.       buffer.scale_min = buffer.cmdmin;
  180.       if( control.verbose )
  181.     (void)printf("  min clipped at %g", buffer.cmdMin);
  182.     } else
  183.       histmin = buffer.scale_min;
  184.     if( buffer.max_given ) {
  185.       if( img.fiscaled )
  186.     buffer.cmdmax = (buffer.cmdMax - img.fibias) / img.fiscale;
  187.       else
  188.     buffer.cmdmax = buffer.cmdMax;
  189.       histmax = MIN(buffer.cmdmax, buffer.scale_max);
  190.       buffer.scale_max = buffer.cmdmax;
  191.       if( control.verbose )
  192.     (void)printf("  max clipped at %g for scaling\n", buffer.cmdMax);
  193.     } else {
  194.       histmax = buffer.scale_max;
  195.       (void)printf(" for scaling\n");
  196.     }
  197.     buffer.hist_area = get_histogram_total(buffer.histogram, histmin, histmax);
  198.   }
  199. }
  200.  
  201. /*
  202.  * Subroutine:    make_histogram
  203.  * Purpose:    Fill in a data histogram for specified buffer subsection
  204.  */
  205. #ifdef ANSIC
  206. static void make_histogram ( short *shortbuf, int *histogram, int ncols,
  207.                  int x, y, width, height, int *area )
  208. {
  209.   *area = width * height;
  210.   memset((void *)histogram, 0, SCALEBUFSZ * sizeof(int));
  211. #else
  212. static void
  213. make_histogram ( shortbuf, histogram, ncols, x, y, width, height, area )
  214.      short *shortbuf;            /* data buffer */
  215.      int *histogram;            /* histogram buffer */
  216.      int ncols;                /* width of data buffer */
  217.      int x, y, width, height;        /* subsection specification */
  218.      int *area;            /* returned values */
  219. {
  220.   *area = width * height;
  221.   bzero((char *)histogram, SCALEBUFSZ * sizeof(int));
  222. #endif
  223.   {
  224.     register short *buf;
  225.     register short *bufend;
  226.     register int *hist;
  227.  
  228.     /* initialize min and max */
  229.     buf = shortbuf + (y * ncols) + x;
  230.     /* offset to zero (+32768 or 0x8000) */
  231.     hist = histogram + SCALEOFF;
  232.     /* if we are reading an entire array, use a simple approach */
  233.     if( ncols == width ) {
  234.       bufend = buf + (*area);
  235.       while( buf < bufend ) {
  236.     ++hist[*buf++];
  237.       }
  238.     } else {
  239.       register short *lineend, *bufend;
  240.       register int jump;
  241.  
  242.       /* if we are reading part of an array, allow for partial line */
  243.       lineend = buf + width;
  244.       jump = ncols - width;
  245.       bufend = buf + (height * ncols);
  246.       while( buf < bufend ) {
  247.     while( buf < lineend ) {
  248.       ++hist[*buf++];
  249.     }
  250.     buf += jump;
  251.     lineend += ncols;
  252.       }
  253.     }
  254.   }
  255. }
  256.  
  257. /*
  258.  * Subroutine:    get_histlims
  259.  * Purpose:    Find the min and max non-zero entries in the histogram
  260.  */
  261. #ifdef ANSIC
  262. static void get_histlims ( int *histogram, int *pmin, int *pmax )
  263. #else
  264. static void get_histlims ( histogram, pmin, pmax )
  265.      int *histogram;
  266.      int *pmin;
  267.      int *pmax;
  268. #endif
  269. {
  270.   register int *hist;
  271.   register int i, limit;
  272.  
  273.   /* offset hist to zero (+32768 or 0x8000)  */
  274.   hist = histogram + SCALEOFF;
  275.   /* count up to first value for min */
  276.   limit = SCALEMAX;
  277.   for( i = SCALEMIN; ((i <= limit) && (hist[i] == 0)); i++ );
  278.   *pmin = i;
  279.   /* count down to last value for max */
  280.   limit = SCALEMIN;
  281.   for( i = SCALEMAX; ((i >= limit) && (hist[i] == 0)); i-- );
  282.   *pmax = i;
  283. }
  284.  
  285. /*
  286.  * Subroutine:    get_histogram_total
  287.  * Purpose:    Find the min and max non-zero entries in the histogram
  288.  */
  289. #ifdef ANSIC
  290. static int get_histogram_total ( int *histogram, int pmin, int pmax )
  291. #else
  292. static int get_histogram_total ( histogram, pmin, pmax )
  293.      int *histogram;
  294.      int pmin;
  295.      int pmax;
  296. #endif
  297. {
  298.   register int *hist;
  299.   register int *end;
  300.   register int count;
  301.  
  302.   /* offset hist to zero (+32768 or 0x8000)  */
  303.   hist = histogram + SCALEOFF;
  304.   end = hist + pmax;
  305.   hist -= pmin;
  306.   count = 0;
  307.   do {
  308.     count += (int)(*hist);
  309.   } while( ++hist <= end );
  310.   return( count );
  311. }
  312.