// Classe Look-Up-Table  pour convertir image en entree ds
// une table de couleur.
//       Classe LUT              R. Ansari  05/95
// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA

#include "machdefs.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#include "lut.h"


/* --Methode-- */

LUT::LUT(double min, double max, unsigned short ncol, int typ, int ntable) 
{
int nlev;

bornes=NULL;
nlev = ncol-2;
if (nlev < 1)  nlev = 1;
bornes = new double[nlev+1];

if (bornes == NULL)  return;
type = typ;  nLevel = nlev;
table = NULL;  
tablenbin = 0;
SetLut(min, max, typ);
return;
}

/* --Methode-- */
LUT::~LUT()
{
if (type<0)  return;
delete[] bornes;
delete[] table;
}

/* --Methode-- */
void LUT::SetLut(double min, double max, int typ, int ntable)
{

if(  (typ != kLutType_Lin)  && (typ != kLutType_Log)
  && (typ != kLutType_Sqrt) && (typ != kLutType_Square)
  )  typ = kLutType_Lin;
type = typ;
if (max <= min)  max = min+1.;
if (nLevel > 0)
  {
  int i;
  double dx;
  double dlx;
  switch (typ)
    {
    case kLutType_Lin :
      dx = (max-min)/(double)nLevel;
      for(i=0; i<nLevel; i++)
        bornes[i] = min+(double)i*dx;
      break;
    case kLutType_Log :
      dlx = log(max-min) / (double)nLevel;
      for(i=0; i<nLevel; i++)
        bornes[i] = min+(double)exp((double)i*dlx);
      break;
    case kLutType_Sqrt :
      dlx = sqrt(max-min) / (double)nLevel;
      for(i=0; i<nLevel; i++)
        bornes[i] = min+((double)i*dlx)*((double)i*dlx);
      break;
    case kLutType_Square :
      dlx = (max-min)*(max-min) / (double)nLevel;
      for(i=0; i<nLevel; i++)
        bornes[i] = min+(double)sqrt((double)i*dlx);
      break;
    default:
      for(i=0; i<nLevel; i++)
        bornes[i] = min;
      break;
    }
  bornes[nLevel] = max; 
  }
else  bornes[0] = 0.5*(min+max);
ComputeTable((ntable > nLevel) ? ntable : tablenbin);
return; 
}

/* --Methode-- */
void LUT::Print()
{
int i;

printf("LUT_Info: Type= %d NLevel= %d Min,Max= %g %g \n",
       type, nLevel, bornes[0], bornes[nLevel]);
for(i=0; i<=nLevel; i++)
  printf("..Bornes[%d] = %g \n", i, bornes[i]);
return;
}

/* --Methode-- */
unsigned short LUT::Apply(double x)
{
int i;
for(i=0;i<=nLevel;i++)  
  if (x < bornes[i])  return(i);
return(nLevel+1);
}

/* --Methode-- */
void LUT::ComputeTable(int nt)
{
if (nt <= 0) nt = 16*(nLevel+2);
else if (nt < (nLevel+2))  nt = (nLevel+2);
tablenbin = nt;
table = new unsigned short [nt-2];
tablebinwidth = (Max()-Min())/(nt-2);
double x = Min()+0.5*tablebinwidth;
for(int i=0; i<nt-2; i++)  { table[i] = Apply(x); x += tablebinwidth; }
}
