#include <assert.h>

#include "cc.h"

namespace OBJREC {

template<class SrcPixelType, class DstPixelType>
void ColorSpace::convert ( NICE::MultiChannelImageT<DstPixelType> & dst, const NICE::MultiChannelImageT<SrcPixelType> & src,
                           int dstColorSpace, int srcColorSpace, double dstM, double srcM )
{
  assert ( ( srcColorSpace >= 0 ) && ( srcColorSpace < NUM_COLORSPACES ) );
  assert ( ( dstColorSpace >= 0 ) && ( dstColorSpace < NUM_COLORSPACES ) );

  dst.reInitFrom ( src );

  if ( ( srcColorSpace == COLORSPACE_RGB ) && ( dstColorSpace == COLORSPACE_HSL ) )
  {
    assert ( dst.channels() == 3 );
    assert ( src.channels() == 3 );

    for ( int y = 0 ; y < src.height() ; y++ )
      for ( int x = 0 ; x < src.width() ; x++)
      {
        double R, G, B, H, S, L;
        R = ( double ) src.get(x,y,0) / srcM;
        G = ( double ) src.get(x,y,1) / srcM;
        B = ( double ) src.get(x,y,2) / srcM;
        ColorConversion::ccRGBtoHSL ( R, G, B, &H, &S, &L );
        dst[0](x,y) = ( DstPixelType ) ( H * dstM );
        dst[1](x,y) = ( DstPixelType ) ( S * dstM );
        dst[2](x,y) = ( DstPixelType ) ( L * dstM );
      }
  }
  else if ( ( srcColorSpace == COLORSPACE_RGB ) && ( dstColorSpace == COLORSPACE_LAB ) )
  {
    for ( int y = 0 ; y < src.height() ; y++ )
      for ( int x = 0 ; x < src.width() ; x++ )
      {
        double R, G, B, X, Y, Z, L, a, b;
        R = ( double ) src.get(x,y,0) / 255.0;
        G = ( double ) src.get(x,y,1) / 255.0;
        B = ( double ) src.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 );
        dst[0](x,y) = ( DstPixelType ) ( L );
        dst[1](x,y) = ( DstPixelType ) ( a );
        dst[2](x,y) = ( DstPixelType ) ( b );
      }
  }
  else if ( ( srcColorSpace == COLORSPACE_LAB ) && ( dstColorSpace == COLORSPACE_RGB ) )
  {
    long k = 0;
    for ( int y = 0 ; y < src.height() ; y++ )
      for ( int x = 0 ; x < src.width() ; x++, k++ )
      {
        double R, G, B, X, Y, Z, L, a, b;
        L = ( double ) src.get(x,y,0);
        a = ( double ) src.get(x,y,1);
        b = ( double ) src.get(x,y,2);
        ColorConversion::ccCIE_LabtoXYZ ( L, a, b, &X, &Y, &Z, 0 );
        ColorConversion::ccXYZtoRGB ( X, Y, Z, &R, &G, &B, 0 );
        dst[0](x,y) = ( DstPixelType ) ( R );
        dst[1](x,y) = ( DstPixelType ) ( G );
        dst[2](x,y) = ( DstPixelType ) ( B );
      }
  }
  else if ( ( srcColorSpace == COLORSPACE_RGB ) && ( dstColorSpace == COLORSPACE_LMS ) )
  {
    long k = 0;
    for ( int y = 0 ; y < src.height() ; y++ )
      for ( int x = 0 ; x < src.width() ; x++, k++ )
      {
        double R, G, B, X, Y, Z, L, M, S;
        R = ( double ) src.get(x,y,0) / srcM;
        G = ( double ) src.get(x,y,1) / srcM;
        B = ( double ) src.get(x,y,2) / srcM;
        ColorConversion::ccRGBtoXYZ ( R, G, B, &X, &Y, &Z, 0 );
        ColorConversion::ccXYZtoLMS ( X, Y, Z, &L, &M, &S );
        dst[0](x,y) = ( DstPixelType ) ( L );
        dst[1](x,y) = ( DstPixelType ) ( M );
        dst[2](x,y) = ( DstPixelType ) ( S );
      }
  }
  else if ( ( srcColorSpace == COLORSPACE_RGB ) && ( dstColorSpace == COLORSPACE_OPP ) )
  {
    long k = 0;
    for ( int y = 0 ; y < src.height() ; y++ )
      for ( int x = 0 ; x < src.width() ; x++, k++ )
      {
        double R, G, B, X, Y, Z, L, M, S, Lum, LM, SLM;
        R = ( double ) src.get(x,y,0) / srcM;
        G = ( double ) src.get(x,y,1) / srcM;
        B = ( double ) src.get(x,y,2) / srcM;
        ColorConversion::ccRGBtoXYZ ( R, G, B, &X, &Y, &Z, 0 );
        ColorConversion::ccXYZtoLMS ( X, Y, Z, &L, &M, &S );
        ColorConversion::ccLMStoOPP ( L, M, S, &Lum, &LM, &SLM );

        dst[0](x,y) = ( DstPixelType ) ( Lum );
        dst[1](x,y) = ( DstPixelType ) ( LM );
        dst[2](x,y) = ( DstPixelType ) ( SLM );
#ifdef DEBUG
        fprintf ( stderr, "R:%.4f G:%.4f B:%.4f X:%.4f Y:%.4f Z:%.4f L:%.4f M:%.4f S:%.4f Lum:%.4f LM:%.4f SLM:%.4f\n", R, G, B, X, Y, Z, L, M, S, Lum, LM, SLM );
#endif
      }
  }
  else {
    fprintf ( stderr, "ColorSpace::convert(): not yet implemented - SrcColorSpace %d -> DstColorSpace %d!!\n", srcColorSpace, dstColorSpace );
    exit ( -1 );
  }

}

}
