#ifndef colors_HSL_Space_H__
#define colors_HSL_Space_H__
#include "Color3_Space.h"
#include "RGB_Space.h"
#include "YUV_Space.h"
#include "../geo/Vectors.h"
#include "../math/utility.h"
#include <cstdlib>
namespace meow {
/*!
* @brief 以浮點數\b Y(亮度), \b U(色度), \b V(濃度) 三個值所組成的色彩空間
*
* 其中範圍都介於0.0~1.0之間
*
* @author cat_leopard
*/
class HSLf_Space: public Color3_Space<double> {
public:
HSLf_Space(): Color3_Space<double>(Vector3D<double>( 0.0, 0.0, 0.0),
Vector3D<double>(PI*2.0, 1.0, 1.0),
Vector3D<double>( 0.0, 0.0, 0.0)) {
}
HSLf_Space(double c): Color3_Space<double>(Vector3D<double>( 0.0, 0.0, 0.0),
Vector3D<double>(PI*2.0, 1.0, 1.0),
Vector3D<double>( c, c, c))
{ }
HSLf_Space(Vector3D<double> const& v):
Color3_Space<double>(Vector3D<double>(0.0, 0.0, 0.0),
Vector3D<double>(1.0, 1.0, 1.0),
Vector3D<double>(v)) {
}
HSLf_Space(HSL_Space const& b): Color3_Space<double>(b) {
}
~HSLf_Space() {
}
double const& hslMin(size_t i) const { return min(i); }
double const& hMin( ) const { return min(0); }
double const& sMin( ) const { return min(1); }
double const& lMin( ) const { return min(2); }
double const& hslMax(size_t i) const { return max(i); }
double const& hMax( ) const { return max(0); }
double const& sMax( ) const { return max(1); }
double const& lMax( ) const { return max(2); }
double const& hsl(size_t i) const { return val(i); }
double const& h( ) const { return hsl(0); }
double const& s( ) const { return hsl(1); }
double const& l( ) const { return hsl(2); }
double const& hsl(size_t i, double c) { return val(i, c); }
double const& h( double c) { return hsl(0, c); }
double const& s( double c) { return hsl(1, c); }
double const& l( double c) { return hsl(2, c); }
double& hslGet(size_t i) { return valGet(i); }
double& hGet( ) { return hslGet(0); }
double& sGet( ) { return hslGet(1); }
double& lGet( ) { return hslGet(2); }
HSLf_Space& operator=(HSLf_Space const& b) {
copyFrom(b);
return *this;
}
HSLf_Space operator+(HSLf_Space const& b) const {
return HSLf_Space(val_ + b.val_);
}
HSLf_Space operator-(HSLf_Space const& b) const {
return HSLf_Space(val_ - b.val_);
}
HSLf_Space operator*(double const& c) const {
return HSLf_Space(val_ * c);
}
HSLf_Space operator/(double const& c) const {
return HSLf_Space(val_ / c);
}
double operator*(HSLf_Space const& b) const {
return val_ * b.val_;
}
};
/*!
* @brief \c RGBf_Space to \c HSLf_Space
*/
inline void colorTransformate(RGBf_Space const& rgb, HSLf_Space* hsl) {
double r = normalize(rgb.rMin(), rgb.rMax(), rgb.r());
double g = normalize(rgb.gMin(), rgb.gMax(), rgb.g());
double b = normalize(rgb.bMin(), rgb.bMax(), rgb.b());
double mx = std::max(std::max(r, g), b);
double mn = std::min(std::min(r, g), b);
double h, s, l;
if (mx == mn ) h = 0;
else if(mx == r && g >= b) h = PI/3.0 * (g-b) / (mx-mn);
else if(mx == r && g < b) h = PI/3.0 * (g-b) / (mx-mn) + PI * 2.0;
else if(mx == g ) h = PI/3.0 * (b-r) / (mx-mn) + PI/3.0*2.0;
else h = PI/3.0 * (r-g) / (mx-mn) + PI/3.0*4.0;
l = 0.5 * (mx + mn);
if (l == 0 || mx == mn) s = 0;
else if(l < 0.5 ) s = (mx - mn) / (2.0 * l);
else s = (mx - mn) / (2 - 2.0 * l);
hsl->h(h);
hsl->s(s);
hsl->l(l);
}
/*!
* @brief \c YUVf_Space to \c HSLf_Space
*/
inline void colorTransformate(YUVf_Space const& yuv, HSLf_Space* hsl) {
RGBf_Space tmp;
colorTransformate(yuv, &tmp);
colorTransformate(tmp, hsl);
}
/*!
* @brief \c HSLf_Space to \c RGBf_Space
*/
inline void colorTransformate(HSLf_Space const& hsl, RGBf_Space* rgb) {
double h = normalize(hsl.hMin(), hsl.hMax(), hsl.h());
double s = normalize(hsl.sMin(), hsl.sMax(), hsl.s());
double l = normalize(hsl.lMin(), hsl.lMax(), hsl.l());
if(s == 0){
rgb->r(denormalize(rgb->rMin(), rgb->rMax(), l));
rgb->g(denormalize(rgb->gMin(), rgb->gMax(), l));
rgb->b(denormalize(rgb->bMin(), rgb->bMax(), l));
return ;
}
double q = (l < 0.5 ? (l * (1 + s)) : (l + s - (l * s)));
double p = 2 * l - q;
double t_r = h + 1.0 / 3.0;
double t_g = h;
double t_b = h - 1.0 / 3.0;
if(t_r < 0) t_r = t_r + 1.0;
if(t_r > 1) t_r = t_r - 1.0;
if(t_g < 0) t_g = t_g + 1.0;
if(t_g > 1) t_g = t_g - 1.0;
if(t_b < 0) t_b = t_b + 1.0;
if(t_b > 1) t_b = t_b - 1.0;
double r, g, b;
if (t_r < 1.0 / 6.0) r = p + (q - p) * 6 * t_r;
else if(t_r < 0.5 ) r = q;
else if(t_r < 2.0 / 3.0) r = p + (q - p) * 6 * (2.0 / 3.0 - t_r);
else r = p;
if (t_g < 1.0 / 6.0) g = p + (q - p) * 6 * t_g;
else if(t_g < 0.5 ) g = q;
else if(t_g < 2.0 / 3.0) g = p + (q - p) * 6 * (2.0 / 3.0 - t_g);
else g = p;
if (t_b < 1.0 / 6.0) b = p + (q - p) * 6 * t_b;
else if(t_b < 0.5 ) b = q;
else if(t_b < 2.0 / 3.0) b = p + (q - p) * 6 * (2.0 / 3.0 - t_b);
else b = p;
rgb->r(denormalize(rgb->rMin(), rgb->rMax(), r));
rgb->g(denormalize(rgb->gMin(), rgb->gMax(), g));
rgb->b(denormalize(rgb->bMin(), rgb->bMax(), b));
}
/*!
* @brief \c HSLf_Space to \c YUVf_Space
*/
inline void colorTransformate(HSLf_Space const& hsl, YUVf_Space* yuv) {
RGBf_Space tmp;
colorTransformate(hsl, &tmp);
colorTransformate(tmp, yuv);
}
/*!
* @brief \c HSLf_Space to \c RGBi_Space
*/
inline void colorTransformate(HSLf_Space const& hsl, RGBi_Space* rgb) {
RGBf_Space tmp;
colorTransformate(hsl, &tmp);
rgb->copyFrom(tmp);
}
/*!
* @brief \c RGBi_Space to \c HSLf_Space
*/
inline void colorTransformate(RGBi_Space const& rgb, HSLf_Space* hsl) {
RGBf_Space tmp;
tmp.copyFrom(rgb);
colorTransformate(rgb, hsl);
}
} // meow
#endif // colors_HSL_Space_H__