/**
 * @file ColorSpace.cpp
 * @brief __DESC__
 * @author Michael Koch
 * @date 07/28/2008
 */

#include "core/image/ImageT.h"
#include "core/vector/VectorT.h"
#include "core/vector/MatrixT.h"

#include <iostream>

#include "ColorSpace.h"
#include <math.h>
#include "vislearning/baselib/cc.h"

using namespace OBJREC;
using namespace std;
using namespace NICE;

//bad position for this function
void ColorSpace::ColorImagetoMultiChannelImage(  const NICE::ColorImage &imgrgb, NICE::MultiChannelImageT<double> &genimg )
{
  genimg.reInit( imgrgb.width(), imgrgb.height(), 3, true );
  for ( int y = 0;y < imgrgb.height();y++ )
  {
    for ( int x = 0;x < imgrgb.width();x++ )
    {
      double r, g, b;
      r = imgrgb.getPixelQuick( x, y, 0 );
      g = imgrgb.getPixelQuick( x, y, 1 );
      b = imgrgb.getPixelQuick( x, y, 2 );
      genimg.set( x, y, r, 0 );
      genimg.set( x, y, g, 1 );
      genimg.set( x, y, b, 2 );
    }
  }
}


//TODO test it
int checkRange( int in, int min = 0, int max = 255 )
{
  int out = in;

  if ( in < min )
  {
    out = min;
  }
  if ( in > max )
  {
    out = max;
  }
  return out;
}

NICE::MultiChannelImageT<double> ColorSpace::rgbtohsl( const NICE::MultiChannelImageT<double> &imgrgb )
{
  NICE::MultiChannelImageT<double> imghsl( imgrgb.width(), imgrgb.height(), 3 );

  for ( int x = 0;x < imgrgb.width();x++ )
  {
    for ( int y = 0;y < imgrgb.height();y++ )
    {
      double R, G, B, H, S, L;

      R = ( double )imgrgb.get( x, y, 0 );
      G = ( double )imgrgb.get( x, y, 1 );
      B = ( double )imgrgb.get( x, y, 2 );
      ColorConversion::ccRGBtoHSL( R, G, B, &H, &S, &L );
      imghsl.set( x, y, H, 0 );
      imghsl.set( x, y, S, 1 );
      imghsl.set( x, y, L, 2 );
    }
  }
  return imghsl;
}

NICE::MultiChannelImageT<double> ColorSpace::hsltorgb( const NICE::MultiChannelImageT<double> &imghsl )
{
  NICE::MultiChannelImageT<double> imgrgb( imghsl.width(), imghsl.height(), 3 );

  for ( int x = 0;x < imghsl.width();x++ )
  {
    for ( int y = 0;y < imghsl.height();y++ )
    {
      double R, G, B, H, S, L;
      H = ( double )imghsl.get( x, y, 0 );
      S = ( double )imghsl.get( x, y, 1 );
      L = ( double )imghsl.get( x, y, 2 );

      ColorConversion::ccHSLtoRGB( H, S, L, &R, &G, &B );

      imgrgb.set( x, y, ( int )round( R*255.0 ), 0 );
      imgrgb.set( x, y, ( int )round( G*255.0 ), 1 );
      imgrgb.set( x, y, ( int )round( B*255.0 ), 2 );
    }
  }
  return imgrgb;
}

NICE::MultiChannelImageT<double> ColorSpace::rgbtolab( const NICE::MultiChannelImageT<double> &imgrgb )
{
  NICE::MultiChannelImageT<double> imglab( imgrgb.width(), imgrgb.height(), 3 );
  //preprocessing RGB to XYZ
  for ( int x = 0;x < imgrgb.width();x++ )
  {
    for ( int y = 0;y < imgrgb.height();y++ )
    {
      double R, G, B, X, Y, Z, L, a, b;
      R = ( double )imgrgb.get( x, y, 0 ) / 255.0;
      G = ( double )imgrgb.get( x, y, 1 ) / 255.0;
      B = ( double )imgrgb.get( x, y, 2 ) / 255.0;
      
      ColorConversion::ccRGBtoXYZ( R, G, B, &X, &Y, &Z, 0 );
      ColorConversion::ccXYZtoCIE_Lab( X, Y, Z, &L, &a, &b, 0 );
      
      imglab.set( x, y, L, 0 );
      imglab.set( x, y, a, 1 );
      imglab.set( x, y, b, 2 );
    }
  }
  return imglab;
}

NICE::MultiChannelImageT<double> ColorSpace::labtorgb( const NICE::MultiChannelImageT<double> &imglab )
{
  NICE::MultiChannelImageT<double> imgrgb( imglab.width(), imglab.height(), 3 );
  //preprocessing RGB to XYZ
  for ( int x = 0;x < imglab.width();x++ )
  {
    for ( int y = 0;y < imglab.height();y++ )
    {
      double R, G, B, X, Y, Z, L, a, b;
      L = imglab.get( x, y, 0 );
      a = imglab.get( x, y, 1 );
      b = imglab.get( x, y, 2 );

      ColorConversion::ccCIE_LabtoXYZ( L, a, b, &X, &Y, &Z, 0 );
      ColorConversion::ccXYZtoRGB( X, Y, Z, &R, &G, &B, 0 );
      imgrgb.set( x, y, round( R*255.0 ), 0 );
      imgrgb.set( x, y, round( G*255.0 ), 1 );
      imgrgb.set( x, y, round( B*255.0 ), 2 );
    }
  }
  return imgrgb;
}

NICE::MultiChannelImageT<double> ColorSpace::rgbtolms( const NICE::MultiChannelImageT<double> &imgrgb )
{
  NICE::MultiChannelImageT<double> imglms = NICE::MultiChannelImageT<double>( imgrgb.width(), imgrgb.height() );
  //preprocessing RGB to XYZ
  for ( int x = 0;x < imgrgb.width();x++ )
  {
    for ( int y = 0;y < imgrgb.height();y++ )
    {
      double R, G, B, X, Y, Z, L, M, S;
      R = imgrgb.get( x, y, 0 ) / 255.0;
      G = imgrgb.get( x, y, 1 ) / 255.0;
      B = imgrgb.get( x, y, 2 ) / 255.0;

      ColorConversion::ccRGBtoXYZ( R, G, B, &X, &Y, &Z, 0 );
      ColorConversion::ccXYZtoLMS( X, Y, Z, &L, &M, &S );
      imglms.set( x, y, L, 0 );
      imglms.set( x, y, M, 1 );
      imglms.set( x, y, S, 2 );
    }
  }
  return imglms;
}