/* color.c */
#include <stdio.h>
#include <math.h>
#include "vector.h"
#include "color.h"
#include "cie.h"
#include "mymath.h"
#include "tonemapping.h"
#include "render.h"

RGB 	NullRGB   = {0.0, 0.0, 0.0},
        Black     = {0.0, 0.0, 0.0},
        Red       = {1.0, 0.0, 0.0},
        Yellow    = {1.0, 1.0, 0.0},
        Green     = {0.0, 1.0, 0.0},
        Turquoise = {0.0, 1.0, 1.0},
        Blue      = {0.0, 0.0, 1.0},
        Magenta   = {1.0, 0.0, 1.0},
        White     = {1.0, 1.0, 1.0};

/* ---------------------------------------------------------------------------
  `RescaleRadiance'

  Rescale real world radiance using appropiately set up tone mapping
  algorithm.     
  ------------------------------------------------------------------------- */
COLOR *RescaleRadiance(COLOR in, COLOR *out)
{
  COLORSCALE(tmopts.pow_bright_adjust, in, in);
  *out = TonemapScaleForDisplay(in);
  return out;
}

RGB *ColorToRGB(COLOR col, RGB *rgb)
{
#ifdef RGBCOLORS
  RGBSET(*rgb, col.spec[0], col.spec[1], col.spec[2]);
#else
  xyz_rgb(col.spec, (float *)rgb);
#endif
  return rgb;
}

COLOR *RGBToColor(RGB rgb, COLOR *col)
{
#ifdef RGBCOLORS
  COLORSET(*col, rgb.r, rgb.g, rgb.b);
#else
  rgb_xyz((float *)&rgb, col->spec);
#endif
  return col;
}

LUV *ColorToLUV(COLOR col, LUV *luv)
{
#ifdef RGBCOLORS
  {
    float xyz[3];
    rgb_xyz(col.spec, xyz);
    xyz_luv(xyz, (float *)luv, CIE_WHITE_Y);	/* CHECK!!! */
  }
#else
  xyz_luv(col.spec, (float *)luv, CIE_WHITE_Y);
#endif
  return luv;
}

COLOR *LUVToColor(LUV luv, COLOR *col)
{
#ifdef RGBCOLORS
  {
    float xyz[3];
    luv_xyz((float *)&luv, xyz, CIE_WHITE_Y);	/* CHECK!!! */
    xyz_rgb(xyz, col->spec);
  }
#else
  luv_xyz((float *)&luv, col->spec, CIE_WHITE_Y);
#endif
  return col;
}

LUV *ColorToDisplayLUV(COLOR col, LUV *luv)
{

  RGB rgb;
  float xyz[3];

  RadianceToRGB(col, &rgb);
  
  rgb_xyz((float*)&rgb, xyz);
  xyz_luv(xyz, (float*)luv, CIE_DISPLAY_WHITE_Y);

  return luv;
}

/* ---------------------------------------------------------------------------
  `ColorToRGB'

  Does most to convert computed radiances to RGB colors ready for display
  on the screen:
 
  1) nonlinear rescale of radiance from the almost unlimited range in
     reality (and the computations) to the limited range of the display
     device.
  2) colormodel conversion from the color model used for the computations
     to an RGB triplet for display on the screen
  3) clipping of RGB values to the range [0,1].

  Gamma correction is performed during rendering.

  MISSING: Gamut mapping
  ------------------------------------------------------------------------- */

/* If the largest RGB color component is larger than 1, this routine
 * rescales all components proportionally so the largest will be equal to
 * 1 now. */
static void RGBClipProp(RGB *rgb)
{
  float s = RGBMAXCOMPONENT(*rgb);
  if (s > 1.) {
    rgb->r /= s;
    rgb->g /= s;
    rgb->b /= s;
  }
}

RGB *RadianceToRGB(COLOR color, RGB *rgb)
{
  RescaleRadiance(color, &color);
  ColorToRGB(color, rgb);
  RGBCLIP(*rgb);
  /*  RGBClipProp(rgb); */
  return rgb;
}

