text: // IDDN FR.001.250001.004.S.X.2019.000.00000
  // ULIS is subject to copyright laws and is the legal and intellectual property of Praxinos,Inc
  /*
  *   ULIS
  *__________________
  * @file         ToHSL.h
  * @author       Clement Berthaud
  * @brief        This file provides the definition for model conversion functions.
  * @copyright    Copyright 2018-2021 Praxinos, Inc. All Rights Reserved.
  * @license      Please refer to LICENSE.md
  */
  #pragma once
  #include "Core/Core.h"
  #include "Process/Conv/Conv.h"
  #include "Image/Color.h"
  #include "Image/Pixel.h"
  #include "Math/Math.h"
  
  ULIS_NAMESPACE_BEGIN
  /////////////////////////////////////////////////////
  // To HSL
  //--------------------------------------------------------------------------------------
  //---------------------------------------------------------------------------- From Grey
  template< typename T, typename U >
  void
  ConvertFormatGreyToHSL( const FPixel iSrc, FPixel iDst, uint32 iLen )
  {
      FColor temp( eFormat::Format_RGBAF );
      while( iLen-- )
      {
          ConvertFormatGreyToRGB< T, ufloat >( iSrc, temp, 1 );
          ConvertFormatRGBToHSL< ufloat, U >( temp, iDst, 1 );
          iSrc.Next();
          iDst.Next();
      }
  }
  
  //--------------------------------------------------------------------------------------
  //----------------------------------------------------------------------------- From RGB
  template< typename T, typename U >
  void
  ConvertFormatRGBToHSL( const FPixel iSrc, FPixel iDst, uint32 iLen )
  {
      while( iLen-- )
      {
          ufloat r = ConvType< T, ufloat >( iSrc.ChannelT< T >( 0 ) );
          ufloat g = ConvType< T, ufloat >( iSrc.ChannelT< T >( 1 ) );
          ufloat b = ConvType< T, ufloat >( iSrc.ChannelT< T >( 2 ) );
          float cmin = FMath::Min3( r, g, b );
          float cmax = FMath::Max3( r, g, b );
          float delta = cmax - cmin;
          float deltaAdd = cmax + cmin;
          float h = 0.f;
          float s = 0.f;
          float l = 0.f;
          l = ( deltaAdd ) / 2.0f;
          if ( delta < FMath::kEpsilonf ){
              h = s = 0.f;
          } else {
              s = ( l < 0.5f ) ? delta / deltaAdd : delta / ( 2.0f - deltaAdd );
              float deltaR = ( ( ( cmax - r ) / 6.0f ) + ( delta / 2.0f ) ) / delta;
              float deltaG = ( ( ( cmax - g ) / 6.0f ) + ( delta / 2.0f ) ) / delta;
              float deltaB = ( ( ( cmax - b ) / 6.0f ) + ( delta / 2.0f ) ) / delta;
                   if( fabs( r - cmax ) < FMath::kEpsilonf )   h = deltaB - deltaG;
              else if( fabs( g - cmax ) < FMath::kEpsilonf )   h = ( 1.0f / 3.0f ) + deltaR - deltaB;
              else if( fabs( b - cmax ) < FMath::kEpsilonf )   h = ( 2.0f / 3.0f ) + deltaG - deltaR;
  
              if( h < 0.0 ) h += 1.0;
              if( h > 1.0 ) h -= 1.0;
          }
  
          iDst.SetChannelT< U >( 0, ConvType< ufloat, U >( h ) );
          iDst.SetChannelT< U >( 1, ConvType< ufloat, U >( s ) );
          iDst.SetChannelT< U >( 2, ConvType< ufloat, U >( l ) );
          iDst.SetAlphaT< U >( ConvType< T, U >( iSrc.AlphaT< T >() ) );
          iSrc.Next();
          iDst.Next();
      }
  }
  
  //--------------------------------------------------------------------------------------
  //----------------------------------------------------------------------------- From HSV
  template< typename T, typename U >
  void
  ConvertFormatHSVToHSL( const FPixel iSrc, FPixel iDst, uint32 iLen )
  {
      FColor temp( eFormat::Format_RGBAF );
      while( iLen-- )
      {
          ConvertFormatHSVToRGB< T, ufloat >( iSrc, temp, 1 );
          ConvertFormatRGBToHSL< ufloat, U >( temp, iDst, 1 );
          iSrc.Next();
          iDst.Next();
      }
  }
  
  //--------------------------------------------------------------------------------------
  //----------------------------------------------------------------------------- From HSL
  template< typename T, typename U >
  void
  ConvertFormatHSLToHSL( const FPixel iSrc, FPixel iDst, uint32 iLen )
  {
      while( iLen-- )
      {
          iDst.SetChannelT< U >( 0, ConvType< T, U >( iSrc.ChannelT< T >( 0 ) ) );
          iDst.SetChannelT< U >( 1, ConvType< T, U >( iSrc.ChannelT< T >( 1 ) ) );
          iDst.SetChannelT< U >( 2, ConvType< T, U >( iSrc.ChannelT< T >( 2 ) ) );
          iDst.SetAlphaT< U >( ConvType< T, U >( iSrc.AlphaT< T >() ) );
          iSrc.Next();
          iDst.Next();
      }
  }
  
  //--------------------------------------------------------------------------------------
  //----------------------------------------------------------------------------- From CMY
  template< typename T, typename U >
  void
  ConvertFormatCMYToHSL( const FPixel iSrc, FPixel iDst, uint32 iLen )
  {
      FColor temp( eFormat::Format_RGBAF );
      while( iLen-- )
      {
          ConvertFormatCMYToRGB< T, ufloat >( iSrc, temp, 1 );
          ConvertFormatRGBToHSL< ufloat, U >( temp, iDst, 1 );
          iSrc.Next();
          iDst.Next();
      }
  }
  
  //--------------------------------------------------------------------------------------
  //---------------------------------------------------------------------------- From CMYK
  template< typename T, typename U >
  void
  ConvertFormatCMYKToHSL( const FPixel iSrc, FPixel iDst, uint32 iLen )
  {
      FColor temp( eFormat::Format_RGBAF );
      while( iLen-- )
      {
          ConvertFormatCMYKToRGB< T, ufloat >( iSrc, temp, 1 );
          ConvertFormatRGBToHSL< ufloat, U >( temp, iDst, 1 );
          iSrc.Next();
          iDst.Next();
      }
  }
  
  //--------------------------------------------------------------------------------------
  //----------------------------------------------------------------------------- From YUV
  template< typename T, typename U >
  void
  ConvertFormatYUVToHSL( const FPixel iSrc, FPixel iDst, uint32 iLen )
  {
      FColor temp( eFormat::Format_RGBAF );
      while( iLen-- )
      {
          ConvertFormatYUVToRGB< T, ufloat >( iSrc, temp, 1 );
          ConvertFormatRGBToHSL< ufloat, U >( temp, iDst, 1 );
          iSrc.Next();
          iDst.Next();
      }
  }
  
  //--------------------------------------------------------------------------------------
  //----------------------------------------------------------------------------- From Lab
  template< typename T, typename U >
  void
  ConvertFormatLabToHSL( const FPixel iSrc, FPixel iDst, uint32 iLen )
  {
      FColor temp( eFormat::Format_RGBAF );
      while( iLen-- )
      {
          ConvertFormatLabToRGB< T, ufloat >( iSrc, temp, 1 );
          ConvertFormatRGBToHSL< ufloat, U >( temp, iDst, 1 );
          iSrc.Next();
          iDst.Next();
      }
  }
  
  //--------------------------------------------------------------------------------------
  //----------------------------------------------------------------------------- From XYZ
  template< typename T, typename U >
  void
  ConvertFormatXYZToHSL( const FPixel iSrc, FPixel iDst, uint32 iLen )
  {
      FColor temp( eFormat::Format_RGBAF );
      while( iLen-- )
      {
          ConvertFormatXYZToRGB< T, ufloat >( iSrc, temp, 1 );
          ConvertFormatRGBToHSL< ufloat, U >( temp, iDst, 1 );
          iSrc.Next();
          iDst.Next();
      }
  }
  
  //--------------------------------------------------------------------------------------
  //----------------------------------------------------------------------------- From Yxy
  template< typename T, typename U >
  void
  ConvertFormatYxyToHSL( const FPixel iSrc, FPixel iDst, uint32 iLen )
  {
      FColor temp( eFormat::Format_RGBAF );
      while( iLen-- )
      {
          ConvertFormatYxyToRGB< T, ufloat >( iSrc, temp, 1 );
          ConvertFormatRGBToHSL< ufloat, U >( temp, iDst, 1 );
          iSrc.Next();
          iDst.Next();
      }
  }
  
  ULIS_NAMESPACE_END
  
  