/******************************************************************************/
/*                                                                            */
/*  COLORMAP - Implement the existing color map on the existing dwell array   */
/*                                                                            */
/******************************************************************************/

#define STRICT
#include <windows.h>
#include <commctrl.h>
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
#include <malloc.h>
#include <new.h>
#include <float.h>

#include "const.h"
#include "classes.h"
#include "extern.h"
#include "funcdefs.h"
#include "julia.rh"

void colormap ()
{
   int irow, icol, itone, index ;
   unsigned int *dwell_ptr ;
   unsigned char *raw_ptr ;
   double min_dwell, max_dwell, hue, brightness, mult, offset, ff, qq, tt ;

/*
   Find the range of dwells.  The minimum will have a brightness equal to
   CmapFloor percent, and the the maximum will have full brightness.
*/

   min_dwell = 1.e60 ;
   max_dwell = -1.e60 ;

   for (irow=0 ; irow<RowResolution ; irow++) {
      dwell_ptr = dwells + irow * ColResolution ;
      for (icol=0 ; icol<ColResolution ; icol++) {
         if (dwell_ptr[icol] > max_dwell)
            max_dwell = dwell_ptr[icol] ;
         if (dwell_ptr[icol] < min_dwell)
            min_dwell = dwell_ptr[icol] ;
         }
      }


   if (min_dwell < CmapNlinear + 1)
      min_dwell = CmapNlinear + 1 ;

   if (max_dwell <= min_dwell)
      max_dwell = min_dwell + 1 ;

   min_dwell = log ( (double) min_dwell ) ;
   max_dwell = log ( (double) max_dwell ) ;
   mult = (CmapNlog - 0.00001) / (max_dwell- min_dwell) ;

   offset = 0.01 * CmapFloor ;

/*
   Implement the color map.  The output image in raw_image has three bytes per
   pixel as R, G, B.  CmapColors different colors will be generated in rotation
   with the color changing for every CmapNdwells dwell increments.
   The brightness will be monotonic with the dwell.
*/

   for (irow=0 ; irow<RowResolution ; irow++) {
      dwell_ptr = dwells + irow * ColResolution ;
      for (icol=0 ; icol<ColResolution ; icol++) {
         raw_ptr = raw_image + (irow * ColResolution + icol) * 3 ;
         if (dwell_ptr[icol] <= CmapNlinear)
            itone = dwell_ptr[icol] ;
         else {
            itone = (int) (mult * (log(dwell_ptr[icol]) - min_dwell)) ; // 0 through CmapNlog-1
            itone += CmapNlinear + 1 ;
            assert ( (unsigned int) itone <= CmapNlinear + CmapNlog ) ;
            }
         // At this point, itone ranges from 0 through CmapNlinear + CmapNlog
         brightness = (double) itone / (CmapNlinear + CmapNlog) ;  // 0-1
         brightness = offset + (1.0 - offset) * brightness ;
         brightness *= 255.99 ;
         hue = (double) ((itone / CmapNdwells) % CmapNcolors) / (double) CmapNcolors ;
         hue = CmapStart + hue * 360.0 ;
         if (hue >= 360.0)
            hue -= 360.0 ;
         // Convert to RGB (with saturation=1)  See foley et al pg. 593
         hue /= 60.0 ;        // Hue is now in [0,6)
         index = (int) hue ;  // 0-5
         ff = hue - index ;
         qq = brightness * (1.0 - ff) ;
         tt = brightness * ff ;
         switch (index) {
            case 0:
               raw_ptr[0] = (unsigned char) brightness ;
               raw_ptr[1] = (unsigned char) tt ;
               raw_ptr[2] = (unsigned char) 0.0 ;
               break ;
            case 1:
               raw_ptr[0] = (unsigned char) qq ;
               raw_ptr[1] = (unsigned char) brightness ;
               raw_ptr[2] = (unsigned char) 0.0 ;
               break ;
            case 2:
               raw_ptr[0] = (unsigned char) 0.0 ;
               raw_ptr[1] = (unsigned char) brightness ;
               raw_ptr[2] = (unsigned char) tt ;
               break ;
            case 3:
               raw_ptr[0] = (unsigned char) 0.0 ;
               raw_ptr[1] = (unsigned char) qq ;
               raw_ptr[2] = (unsigned char) brightness ;
               break ;
            case 4:
               raw_ptr[0] = (unsigned char) tt ;
               raw_ptr[1] = (unsigned char) 0.0 ;
               raw_ptr[2] = (unsigned char) brightness ;
               break ;
            case 5:
               raw_ptr[0] = (unsigned char) brightness ;
               raw_ptr[1] = (unsigned char) 0.0 ;
               raw_ptr[2] = (unsigned char) qq ;
               break ;
            }
         }
      }

}
