19 #ifndef SNARK_GRAPHICS_COLOUR_HEADER_GUARD_
20 #define SNARK_GRAPHICS_COLOUR_HEADER_GUARD_
22 #include <boost/lexical_cast.hpp>
23 #include <comma/base/exception.h>
24 #include <comma/math/compare.h>
25 #include <comma/Point/Point.h>
26 #include <comma/visiting/traits.h>
28 namespace snark {
namespace graphics {
31 template <
typename T >
34 typedef T numeric_type;
35 static numeric_type min() {
return 0; }
36 static numeric_type max() {
return 1; }
43 typedef unsigned int numeric_type;
44 static numeric_type min() {
return 0; }
45 static numeric_type max() {
return 255; }
49 template <
typename T >
50 class colour :
public comma::Point< T, 4 >
74 template <
typename S >
111 typedef comma::Point< T, 4 >
Base;
117 colour operator-()
const {
return colour( colour_traits< T >::max() -
red(), colour_traits< T >::max() -
green(), colour_traits< T >::max() -
blue() ); }
119 const colour& operator*=(
double d );
120 const colour& operator-=(
const colour& rhs ) {
return operator+=( -rhs ); }
121 const colour& operator/=(
double d ) {
return operator*=( 1 / d ); }
122 colour operator+(
const colour& rhs )
const {
colour c( *
this ); c += rhs;
return c; }
123 colour operator-(
const colour& rhs )
const {
colour c( *
this ); c -= rhs;
return c; }
124 colour operator*(
double d )
const {
colour c( *
this ); c *= d;
return c; }
125 colour operator/(
double d )
const {
colour c( *
this ); c /= d;
return c; }
128 static colour< T >
fromString(
const std::string& rgba );
139 template <
typename T >
140 inline void validate( T t )
142 if( math::less( t, colour_traits< T >::min() ) || math::less( colour_traits< T >::max(), t ) )
144 COMMA_THROW( comma::exception,
"expected value in [" << colour_traits< T >::min() <<
", " << colour_traits< T >::max() <<
"], got " << t );
148 template <
typename T > T fromString(
const std::string& s ) {
return boost::lexical_cast< T >( s ); }
151 inline unsigned char fromString< unsigned char >(
const std::string& s )
153 unsigned char high =
static_cast< unsigned char >( s.at( 0 ) );
154 unsigned char low =
static_cast< unsigned char >( s.at( 1 ) );
155 return 16 * (
'0' <= high && high <=
'9' ? high -
'0' :
'a' <= high && high <=
'f' ? high -
'a' - 10 : high -
'A' - 10 )
156 +
'0' <= low && low <=
'9' ? low -
'0' :
'a' <= low && low <=
'f' ? low -
'a' - 10 : low -
'A' - 10;
164 if( ( rgba.length() != 8 && rgba.length() != 10 ) || rgba.at( 0 ) !=
'0' || ( rgba.at( 1 ) !=
'x' && rgba.at( 1 ) !=
'X' ) ) { COMMA_THROW( graphics::exception,
"expected hex colour, got \"" << rgba <<
"\"" ); }
165 colour< unsigned char > c( impl::fromString< unsigned char >( rgba.substr( 2 ) )
166 , impl::fromString< unsigned char >( rgba.substr( 4 ) )
167 , impl::fromString< unsigned char >( rgba.substr( 6 ) ) );
168 if( rgba.length() == 10 ) { c.alpha( impl::fromString< unsigned char >( rgba.substr( 8 ) ) ); }
172 template <
typename T >
178 template <
typename T >
209 template <
typename T >
210 template <
typename S >
213 typedef typename S::Type Type;
216 return S( static_cast< Type >( (
float( this->red() ) / ft ) * fs )
217 , static_cast< Type >( (
float( this->green() ) / ft ) * fs )
218 , static_cast< Type >( (
float( this->blue() ) / ft ) * fs )
219 , static_cast< Type >( (
float( this->alpha() ) / ft ) * fs ) );
222 template <
typename T >
225 template <
typename T >
228 template <
typename T >
231 template <
typename T >
234 template <
typename T >
238 this->operator[]( 0 ) = t;
242 template <
typename T >
246 this->operator[]( 1 ) = t;
250 template <
typename T >
254 this->operator[]( 2 ) = t;
258 template <
typename T >
262 this->operator[]( 3 ) = t;
266 template <
typename T >
269 float f =
static_cast< float> ( d );
271 green( green() * f );
273 alpha( alpha() * f );
277 template <
typename T >
283 template <
typename T >
289 template <
typename T >
297 namespace snark {
namespace Visiting {
303 template <
typename Key,
class Visitor >
306 v.apply(
"r", p.
red() );
307 v.apply(
"g", p.
green() );
308 v.apply(
"b", p.
blue() );
309 v.apply(
"a", p.
alpha() );
313 template <
typename Key,
class Visitor >