home *** CD-ROM | disk | FTP | other *** search
/ Encyclopedia of Graphics File Formats Companion / GFF_CD.ISO / software / unix / saoimage / sao1_07.tar / sclmap.c < prev    next >
C/C++ Source or Header  |  1990-04-20  |  9KB  |  293 lines

  1. #ifndef lint
  2. static char SccsId[] = "%W%  %G%";
  3. #endif
  4.  
  5. /* Module:    sclmap.c (Scale Map)
  6.  * Purpose:    Map image values to display screen values using various
  7.  *        functions
  8.  * Subroutine:    make_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          26 May 1989
  16.  *        {n} <who> -- <does what> -- <when>
  17.  */
  18.  
  19. #include <stdio.h>        /* get stderr, NULL, etc. */
  20. #include <math.h>        /* get the math definitions */
  21. #include <X11/Xlib.h>        /* X window stuff */
  22. #include <X11/Xutil.h>        /* X window manager stuff */
  23. #include "hfiles/constant.h"    /* define codes  */
  24. #include "hfiles/struct.h"    /* declare structure types */
  25. #include "hfiles/extern.h"    /* extern main parameter structures */
  26. #include "hfiles/scale.h"    /* define scaling constants */
  27.  
  28. #ifndef SUN
  29. #define expm1(a)  (exp(a)-1)
  30. #endif
  31.  
  32. /*
  33.  * Subroutine:    make_scalemap
  34.  * Purpose:    Make scale map according to type selected
  35.  * Note:    Map goes from image value to hardware value (through ideal
  36.  *        map value using pixels array from XAllocColors)
  37.  */
  38. void make_scalemap ( image_min, image_max )
  39.      int image_min, image_max;    /* i: range of mapping for image data input */
  40. {
  41.   void histogram_equalize();
  42.   static void linear_scale(), wrap_scale(), sqrt_scale(), log_scale();
  43.  
  44.   /* note the range of data for which mapping is to be calculated */
  45.   if( image_max == image_min )
  46.     ++image_max;
  47.   if( image_max < image_min ) {
  48.     int temp;
  49.     temp = image_max;
  50.     image_max = image_min;
  51.     image_min = temp;
  52.   }
  53.   {
  54.     /* fill in map below min with mincolor */
  55.     register int imageval;
  56.     register int pixval;
  57.     register unsigned char *lookup;    /* l: scalemap base (signed index) */
  58.     lookup = buffer.scalemap + SCALEOFF;
  59.     pixval = color.pixvalmap[0];
  60.     for( imageval = -32768; imageval < image_min; imageval++ )
  61.       lookup[imageval] = pixval;
  62.   }
  63.   /* create the image map straight or with some form of scaling */
  64.   switch( color.scale.mode ) {
  65.   case SOP_HistEq:
  66.     /* if there are levels to distribute, call the routine, else do the next */
  67.     if( color.ncolors < (image_max - image_min) ) {
  68.       histogram_equalize(buffer.scalemap + SCALEOFF,
  69.              buffer.histogram + SCALEOFF, buffer.hist_area,
  70.              image_min, image_max,
  71.              color.ncolors, color.pixvalmap);
  72.       break;
  73.     }
  74.     /* fall through to linear if there is nothing to distribute */
  75.   case SOP_Linear:
  76.     linear_scale(image_min, image_max);
  77.     break;
  78.   case SOP_Wrap:
  79.     wrap_scale(image_min, image_max);
  80.     /* don't fill in the top of map */
  81.     return;
  82.   case SOP_Sqrt:
  83.     sqrt_scale(image_min, image_max);
  84.     break;
  85.   case SOP_Log:
  86.     log_scale(image_min, image_max);
  87.     break;
  88.   default:
  89.     (void)fprintf(stderr,"Unknown scaling type request!\n");
  90.   }
  91.   {
  92.     /* fill in top of map with maxcolor */
  93.     register int imageval;
  94.     register int pixval;
  95.     register unsigned char *lookup;    /* l: scalemap base (signed index) */
  96.     lookup = buffer.scalemap + SCALEOFF;
  97.     pixval = color.pixvalmap[color.ncolors - 1];
  98.     for( imageval = image_max; imageval < 32768; imageval++ )
  99.       lookup[imageval] = pixval;
  100.   }
  101. }
  102.  
  103. /*
  104.  * Subroutine:    linear_scale
  105.  * Purpose:    Distribute color levels in the map evenly
  106.  */
  107. static void linear_scale ( image_min, image_max )
  108.   int image_min, image_max;        /* i: limits of values in display */
  109. {
  110.   double scale;
  111.   double upper_bound;
  112.   int maxcolor;
  113.   int level;
  114.   unsigned long *pixels;        /* l: ideal byte to hardare byte map */
  115.   register unsigned char *lookup;    /* l: scalemap base (signed offsets) */
  116.   register int imageval;
  117.   register int pixval;
  118.   register int imagelim;
  119.  
  120.   lookup = buffer.scalemap + SCALEOFF;
  121.   maxcolor = color.ncolors - 1;
  122.   pixels = color.pixvalmap;
  123.   /* input range / output range yields input cells per ouput cell */
  124.   scale = (double)(image_max - image_min + 1) / (double)color.ncolors;
  125.   imageval = image_min;
  126.   /* upper bound is ideal edge between colors (offset for rounding) */
  127.   upper_bound = image_min + 0.5;
  128.   level = 0;
  129.   pixval = pixels[0];
  130.   while( level++ < maxcolor ) {
  131.     upper_bound += scale;
  132.     imagelim = (int)upper_bound;
  133.     while( imageval < imagelim )
  134.       lookup[imageval++] = pixval;
  135.     /* level was inc'd after loop test, make pixval for next round */
  136.     pixval = pixels[level];
  137.   }
  138.   /* fill in at top if short of image_max */
  139.   while( imageval <= image_max )
  140.     lookup[imageval++] = pixval;
  141. }
  142.  
  143. /*
  144.  * Subroutine:    wrap_scale
  145.  * Purpose:    Create the image map with a repeating linear scale
  146.  * Note:    Levels below image_min are not mapped
  147.  */
  148. static void wrap_scale ( image_min, image_max )
  149.   int image_min, image_max;    /* i: limits of values in display */
  150. {
  151.   double scale;
  152.   double range;
  153.   int maxcolor;
  154.   int level;
  155.   unsigned long *pixels;        /* l: ideal byte to hardare byte map */
  156.   register unsigned char *lookup;    /* l: scalemap base (signed offsets) */
  157.   register int imageval;
  158.   register int pixval;
  159.   register int imagelim;
  160.  
  161.   lookup = buffer.scalemap + SCALEOFF;
  162.   maxcolor = color.ncolors - 1;
  163.   pixels = color.pixvalmap;
  164.   /* input range / output range yields input cells per ouput cell */
  165.   imagelim = (image_max - image_min + 1) / color.scale.wrap_cnt;
  166.   scale = (double)imagelim / (double)color.ncolors;
  167.   /* start at image_min with color level = 0 */
  168.   imageval = image_min;
  169.   level = 0;
  170.   /* use range as floating point boundary between levels */
  171.   range = (double)imageval;
  172.   while( imageval < 32768 ) {
  173.     do {
  174.       /* level was inc'd after loop test, make pixval for next round */
  175.       pixval = pixels[level];
  176.       range += scale;
  177.       imagelim = (int)(range + 0.5);
  178.       if( imagelim >= 32768 ) 
  179.     imagelim = 32767;
  180.       do {
  181.     lookup[imageval] = pixval;
  182.       } while( ++imageval <= imagelim );
  183.       if( imageval >= 32768 )
  184.     return;
  185.     } while( ++level <= maxcolor );
  186.     /* pixval at level 0 lowest color again */
  187.     level = 0;
  188.   }
  189. }
  190.  
  191. /*
  192.  * Subroutine:    sqrt_scale
  193.  * Purpose:    Distribute color levels in the map by a root or power function.
  194.  * Method:    (level / maxlevel) ranges from 0 to 1.  Raise to a power.
  195.  *        Result curves from 0 to 1.  Map result directly back to
  196.  *        pixel value.
  197.  */
  198. static void sqrt_scale ( image_min, image_max )
  199.   int image_min, image_max;        /* i: limits of values in display */
  200. {
  201.   double range;
  202.   double power;
  203.   double ncolors;
  204.   int maxcolor;
  205.   int level;
  206.   unsigned long *pixels;        /* l: ideal byte to hardare byte map */
  207.   register unsigned char *lookup;    /* l: scalemap base (signed offsets) */
  208.   register int imageval;
  209.   register int pixval;
  210.   register int imagelim;
  211.  
  212.   lookup = buffer.scalemap + SCALEOFF;
  213.   maxcolor = color.ncolors - 1;
  214.   pixels = color.pixvalmap;
  215.   power = color.scale.root_power;
  216.   ncolors = (double)color.ncolors;
  217.   range = image_max - image_min + 1;
  218.   imageval = image_min;
  219.   level = 0;
  220.   /* pixval at level 0 is pixoffset (lshifted 0 is still 0) */
  221.   pixval = pixels[0];
  222.   while( level++ < maxcolor ) {
  223.     imagelim = image_min + (int)
  224.       ((pow(((double)level / ncolors), power) * range) + 0.5);
  225.     /* limit map range to image values */
  226.     if( imagelim > image_max )
  227.       imagelim = image_max;
  228.     while( imageval < imagelim )
  229.       lookup[imageval++] = pixval;
  230.     /* level was inc'd after loop test, make pixval for next round */
  231.     pixval = pixels[level];
  232.   }
  233.   /* fill in at top if short of image_max */
  234.   while( imageval <= image_max )
  235.     lookup[imageval++] = pixval;
  236. }
  237.  
  238. /*
  239.  * Subroutine:    log_scale
  240.  * Purpose:    Distribute color levels in the map by a logorithmic or
  241.  *        exponential curve (powers of e).
  242.  */
  243. static void log_scale ( image_min, image_max )
  244.   int image_min, image_max;        /* i: limits of values in display */
  245. {
  246.   double scale;
  247.   double expo;
  248.   double ncolors;
  249.   int maxcolor;
  250.   int level;
  251.   unsigned long *pixels;        /* l: ideal byte to hardare byte map */
  252.   register unsigned char *lookup;    /* l: scalemap base (signed offsets) */
  253.   register int imageval;
  254.   register int pixval;
  255.   register int imagelim;
  256.  
  257.   lookup = buffer.scalemap + SCALEOFF;
  258.   maxcolor = color.ncolors - 1;
  259.   pixels = color.pixvalmap;
  260.   expo = color.scale.log_expo;
  261.   ncolors = (double)color.ncolors;
  262.   /* base distribution on e**n as n goes from 0 to expo (expm1 is exp()-1) */
  263.   if( color.scale.log_expo >= 0 ) {
  264.     scale = (double)(image_max - image_min + 1) / expm1(expo);
  265.   } else {
  266.     /* negative exponents allocate more levels toward the high values */
  267.     scale = (double)(image_max - image_min + 1) / (1.0 - exp(expo));
  268.   }
  269.   imageval = image_min;
  270.   level = 0;
  271.   /* pixval at level 0 is pixoffset (lshifted 0 is still 0) */
  272.   pixval = pixels[0];
  273.   while( level++ < maxcolor ) {
  274.     if( expo > 0 ) {
  275.       imagelim = image_min + (int)
  276.     ((expm1(((double)level / ncolors) * expo) * scale) + 0.5);
  277.     } else {
  278.       imagelim = image_min + (int)
  279.     ((1.0-exp(((double)level / ncolors) * expo) * scale) + 0.5);
  280.     }
  281.     /* limit map range to image values */
  282.     if( imagelim > image_max )
  283.       imagelim = image_max;
  284.     while( imageval < imagelim )
  285.       lookup[imageval++] = pixval;
  286.     /* level was inc'd after loop test, make pixval for next round */
  287.     pixval = pixels[level];
  288.   }
  289.   /* fill in at top if short of image_max */
  290.   while( imageval <= image_max )
  291.     lookup[imageval++] = pixval;
  292. }
  293.