Radium Engine  1.5.0
Color.hpp
1 #pragma once
2 
3 #include <Core/CoreMacros.hpp>
4 #include <Core/Math/Math.hpp>
5 #include <Eigen/Core>
6 #include <Eigen/Geometry> //homogeneous
7 #include <random>
8 
9 namespace Ra {
10 namespace Core {
11 namespace Utils {
12 
21 uint32_t RA_CORE_API getNamedColorCode( std::string_view name );
22 
37 template <typename _Scalar>
38 class ColorBase : public Eigen::Matrix<_Scalar, 4, 1>
39 {
40  public:
41  using VectorType = Eigen::Matrix<_Scalar, 4, 1>;
42 
43  explicit inline ColorBase() : ColorBase( _Scalar( 1. ), _Scalar( 1. ), _Scalar( 1. ) ) {}
44 
45  template <typename S2>
46  inline ColorBase( S2 r, S2 g, S2 b, S2 alpha = S2( 1 ) ) :
47  VectorType( _Scalar( r ), _Scalar( g ), _Scalar( b ), _Scalar( alpha ) ) {}
48 
50  template <typename S2>
51  inline ColorBase( const ColorBase<S2>& other ) : VectorType( other.template cast<_Scalar>() ) {}
52 
54  template <typename Derived>
55  inline ColorBase( const Eigen::MatrixBase<Derived>& v ) :
56  VectorType( v.template cast<_Scalar>() ) {}
57 
59  operator VectorType() { return *this; }
60 
62  static inline ColorBase sRGBToLinearRGB( const ColorBase& srgb ) {
63  ColorBase<_Scalar> c( srgb );
64  for ( auto& u : c.rgb() ) {
65  if ( u < 0.04045_ra ) { u /= 12.92_ra; }
66  else { u = std::pow( ( u + 0.055_ra ) / 1.055_ra, 2.4_ra ); }
67  }
68  return c;
69  }
70 
72  static inline ColorBase linearRGBTosRGB( const ColorBase& lrgb ) {
73  ColorBase<_Scalar> c( lrgb );
74  for ( auto& u : c.rgb() ) {
75  if ( u < 0.0031308_ra ) { u *= 12.92_ra; }
76  else { u = 1.055_ra * std::pow( u, 1_ra / 2.4_ra ) - 0.055_ra; }
77  }
78  return c;
79  }
80 
81  template <typename Derived>
82  static inline ColorBase fromRGB( const Eigen::MatrixBase<Derived>& rgb,
83  Scalar alpha = Scalar( 1. ) ) {
84  ColorBase c( rgb.template cast<_Scalar>().homogeneous() );
85  c.alpha() = alpha;
86  return c;
87  }
88 
89  Eigen::Block<VectorType, 3, 1> rgb() { return ( *this ).template head<3>(); }
90  const Eigen::Block<VectorType, 3, 1> rgb() const { return ( *this ).template head<3>(); }
91 
92  Scalar alpha() const { return ( *this )( 3 ); }
93  Scalar& alpha() { return ( *this )( 3 ); }
94  bool hasValidAlpha() const { return Math::checkRange( alpha(), 0_ra, 1_ra ); }
95 
96  static inline ColorBase<_Scalar> Alpha() {
97  return ColorBase<_Scalar>( _Scalar( 0. ), _Scalar( 0. ), _Scalar( 0. ), _Scalar( 0. ) );
98  }
99 
100  static inline ColorBase<_Scalar> Black() {
101  return ColorBase<_Scalar>( _Scalar( 0. ), _Scalar( 0. ), _Scalar( 0. ) );
102  }
103 
104  static inline ColorBase<_Scalar> Red() {
105  return ColorBase<_Scalar>( _Scalar( 1. ), _Scalar( 0. ), _Scalar( 0. ) );
106  }
107 
108  static inline ColorBase<_Scalar> Green() {
109  return ColorBase<_Scalar>( _Scalar( 0. ), _Scalar( 1. ), _Scalar( 0. ) );
110  }
111 
112  static inline ColorBase<_Scalar> Blue() {
113  return ColorBase<_Scalar>( _Scalar( 0. ), _Scalar( 0. ), _Scalar( 1. ) );
114  }
115 
116  static inline ColorBase<_Scalar> Yellow() {
117  return ColorBase<_Scalar>( _Scalar( 1. ), _Scalar( 1. ), _Scalar( 0. ) );
118  }
119 
120  static inline ColorBase<_Scalar> Magenta() {
121  return ColorBase<_Scalar>( _Scalar( 1. ), _Scalar( 0. ), _Scalar( 1. ) );
122  }
123 
124  static inline ColorBase<_Scalar> Cyan() {
125  return ColorBase<_Scalar>( _Scalar( 0. ), _Scalar( 1. ), _Scalar( 1. ) );
126  }
127 
128  static inline ColorBase<_Scalar> White() {
129  return ColorBase<_Scalar>( _Scalar( 1. ), _Scalar( 1. ), _Scalar( 1. ) );
130  }
131 
132  static inline ColorBase<_Scalar> Grey( _Scalar f = _Scalar( 0.5 ), _Scalar a = _Scalar( 1. ) ) {
133  return ColorBase<_Scalar>( f, f, f, a );
134  }
135 
136  static inline ColorBase<_Scalar> Skin() {
137  return ColorBase<_Scalar>( _Scalar( 1.0 ), _Scalar( 0.87 ), _Scalar( 0.74 ) );
138  }
139 
144  static inline ColorBase<_Scalar> getNamedColor( std::string_view name ) {
145  return fromRGB24( getNamedColorCode( name ) );
146  }
147 
148  // Convert to/from various int formats
149 
150  static inline ColorBase<_Scalar> fromChars( uchar r, uchar g, uchar b, uchar a = 0xff ) {
151  return ColorBase<_Scalar>( _Scalar( r ) / 255.0f,
152  _Scalar( g ) / 255.0f,
153  _Scalar( b ) / 255.0f,
154  _Scalar( a ) / 255.0f );
155  }
156 
157  static inline ColorBase<_Scalar> fromRGB24( uint32_t rgb ) {
158  uchar r = uchar( ( rgb >> 16 ) & 0xff );
159  uchar g = uchar( ( rgb >> 8 ) & 0xff );
160  uchar b = uchar( ( rgb >> 0 ) & 0xff );
161  return fromChars( r, g, b );
162  }
163 
164  static inline ColorBase<_Scalar> fromRGBA32( uint32_t rgba ) {
165  uchar r = uchar( ( rgba >> 24 ) & 0xff );
166  uchar g = uchar( ( rgba >> 16 ) & 0xff );
167  uchar b = uchar( ( rgba >> 8 ) & 0xff );
168  uchar a = uchar( ( rgba >> 0 ) & 0xff );
169  return fromChars( r, g, b, a );
170  }
171 
172  static inline ColorBase<_Scalar> fromARGB32( uint32_t argb ) {
173  uchar a = uchar( ( argb >> 24 ) & 0xff );
174  uchar r = uchar( ( argb >> 16 ) & 0xff );
175  uchar g = uchar( ( argb >> 8 ) & 0xff );
176  uchar b = uchar( ( argb >> 0 ) & 0xff );
177  return fromChars( r, g, b, a );
178  }
179 
180  static inline ColorBase<_Scalar> fromHSV( const _Scalar hue,
181  const _Scalar saturation = 1.0,
182  const _Scalar value = 1.0,
183  const _Scalar alpha = 1.0 ) {
184  ColorBase<_Scalar> c;
185 
186  if ( saturation == 0.0f ) {
187  c[0] = c[1] = c[2] = value;
188  c[3] = alpha;
189  return c;
190  }
191  _Scalar h = ( ( hue == 1.0f ) ? 0.0f : hue ) * 6.0f;
192  int i = int( std::floor( h ) );
193  _Scalar v1 = value * ( 1.0f - saturation );
194  _Scalar v2 = value * ( 1.0f - ( saturation * ( h - i ) ) );
195  _Scalar v3 = value * ( 1.0f - ( saturation * ( 1.0f - h - i ) ) );
196  switch ( i ) {
197  case 0: {
198  c[0] = value;
199  c[1] = v3;
200  c[2] = v1;
201  } break;
202  case 1: {
203  c[0] = v2;
204  c[1] = value;
205  c[2] = v1;
206  } break;
207  case 2: {
208  c[0] = v1;
209  c[1] = value;
210  c[2] = v3;
211  } break;
212  case 3: {
213  c[0] = v1;
214  c[1] = v2;
215  c[2] = value;
216  } break;
217  case 4: {
218  c[0] = v3;
219  c[1] = v1;
220  c[2] = value;
221  } break;
222  default: {
223  c[0] = value;
224  c[1] = v1;
225  c[2] = v2;
226  } break;
227  }
228  c[3] = alpha;
229  return c;
230  }
231 
232  inline uint32_t toRGBA32() const {
233  ColorBase<_Scalar> c( ( *this ) * 255 );
234  Eigen::Matrix<int, 4, 1> scaled( c.x(), c.y(), c.z(), c.w() );
235  return ( uint32_t( scaled( 0 ) ) << 24 ) | ( uint32_t( scaled( 1 ) ) << 16 ) |
236  ( uint32_t( scaled( 2 ) ) << 8 ) | ( uint32_t( scaled( 3 ) ) << 0 );
237  }
238 
239  inline uint32_t toARGB32() const {
240  ColorBase<_Scalar> c( ( *this ) * 255 );
241  Eigen::Matrix<int, 4, 1> scaled( c.x(), c.y(), c.z(), c.w() );
242  return ( uint32_t( scaled( 3 ) ) << 24 ) | ( uint32_t( scaled( 0 ) ) << 16 ) |
243  ( uint32_t( scaled( 1 ) ) << 8 ) | ( uint32_t( scaled( 2 ) ) << 0 );
244  }
245 
246  static inline std::vector<ColorBase<_Scalar>> scatter( const uint size, const _Scalar gamma ) {
247  std::vector<ColorBase<_Scalar>> color( size );
248  if ( size > 1 )
249  for ( uint i = 0; i < size; ++i ) {
250  color[i] = fromHSV( ( _Scalar( i ) / _Scalar( size - 1 ) ) * 0.777 );
251  color[i] = ( color[i] + ColorBase<_Scalar>::Constant( gamma ) ) * 0.5;
252  }
253  else { color[0] = Red(); }
254  std::shuffle( color.begin(), color.end(), std::mt19937( std::random_device()() ) );
255  return color;
256  }
257 };
258 
259 using Color = ColorBase<Scalar>;
260 using Colorf = ColorBase<float>;
261 using Colord = ColorBase<double>;
262 
263 } // namespace Utils
264 } // namespace Core
265 } // namespace Ra
static ColorBase sRGBToLinearRGB(const ColorBase &srgb)
convert the color expressed in sRGB color space to linear RGB
Definition: Color.hpp:62
static ColorBase linearRGBTosRGB(const ColorBase &lrgb)
convert the color expressed in linear RGB color space to sRGB
Definition: Color.hpp:72
static ColorBase< _Scalar > getNamedColor(std::string_view name)
Definition: Color.hpp:144
ColorBase(const ColorBase< S2 > &other)
Copy constructor.
Definition: Color.hpp:51
ColorBase(const Eigen::MatrixBase< Derived > &v)
Copy constructor from Eigen expressions: ColorBase<_Scalar> c( (*this) * 255 );
Definition: Color.hpp:55
bool checkRange(const Vector_Or_Scalar &v, const Scalar &min, const Scalar &max)
Definition: Math.hpp:53
Definition: Cage.cpp:3