Created
January 14, 2013 09:42
-
-
Save usagi/4528935 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <stdexcept> | |
#include <limits> | |
#include <set> | |
#include <cmath> | |
#include <algorithm> | |
#include <string> | |
using namespace std; | |
struct RGB24 { uint8_t r, g, b; }; | |
template<class T> | |
struct HSL { T h, s, l; }; | |
using HSL24 = HSL<uint8_t>; | |
using HSL192F = HSL<double>; | |
bool operator<(const RGB24& a,const RGB24& b) { | |
if ( a.b > b.b || a.g > b.g ) return false; | |
return a.r < b.r; | |
} | |
bool operator==(const RGB24& a,const RGB24& b) { | |
return a.r == b.r && a.g == b.g && a.b == b.b; | |
} | |
template<class INTERNAL_TYPE = double, class RGB_TYPE = RGB24, class HSL_TYPE = HSL192F> | |
HSL_TYPE hsl_from_rgb(RGB_TYPE&& i){ | |
using internal_type = INTERNAL_TYPE; | |
using rgb_type = RGB_TYPE; | |
constexpr internal_type | |
zero = 0., one = 1., two = 2., six = 6., | |
binary_1 = 1. / 2., | |
max_factor = numeric_limits<decltype(i.r)>::max(), | |
unorm_factor = one / max_factor; | |
const auto | |
r = internal_type( i.r ) * unorm_factor, | |
g = internal_type( i.g ) * unorm_factor, | |
b = internal_type( i.b ) * unorm_factor; | |
const auto | |
max_value = max({r, g, b}), | |
min_value = min({r, g, b}); | |
const auto l = (max_value + min_value) * binary_1; | |
if (max_value == min_value) | |
return {zero, zero, l}; | |
auto d = max_value - min_value; | |
const auto s = d / ( | |
(l > binary_1) | |
? (two - max_value - min_value) | |
: (max_value + min_value) | |
); | |
if (max_value == r) | |
return {(g - b) / d + (g < b ? 6 : 0), s, l}; | |
if (max_value == g) | |
return {(g - r) / d + 2, s, l}; | |
return {(r - g) / d + 4, s, l}; | |
} | |
template<class HSL_TYPE> | |
HSL_TYPE calc_resolution_of_HSL_from_RGB24(){ | |
using type_of_RGB24_value = decltype(RGB24::r); | |
constexpr size_t max_of_RGB24_value = numeric_limits<type_of_RGB24_value>::max(); | |
constexpr size_t max_of_RGB24_value_plus_one = max_of_RGB24_value + 1; | |
set<double> h_list, s_list, l_list; | |
array<type_of_RGB24_value, max_of_RGB24_value_plus_one> ns; | |
iota(ns.begin(), ns.end(), 0); | |
static_assert(sizeof(type_of_RGB24_value) <= sizeof(uint8_t), "oops!"); | |
for(uint_fast16_t r = 0; r < max_of_RGB24_value_plus_one; ++r) | |
for(const auto& g : ns) | |
for(const auto& b : ns) { | |
auto&& hsl = hsl_from_rgb<double>({ | |
static_cast<decltype(RGB24::r)>(r), | |
static_cast<decltype(RGB24::g)>(g), | |
static_cast<decltype(RGB24::b)>(b), | |
}); | |
h_list.insert(move(hsl.h)); | |
s_list.insert(move(hsl.s)); | |
l_list.insert(move(hsl.l)); | |
} | |
HSL_TYPE hsl; | |
constexpr double double_max = numeric_limits<double>::max(); | |
double d; | |
auto f = [&d](double a, double b){ d = min(d, b - a); return false; }; | |
d = double_max; adjacent_find(h_list.begin(), h_list.end(), f); hsl.h = d; | |
d = double_max; adjacent_find(s_list.begin(), s_list.end(), f); hsl.s = d; | |
d = double_max; adjacent_find(l_list.begin(), l_list.end(), f); hsl.l = d; | |
return hsl; | |
} | |
int main() try { | |
auto calculated_resolution = calc_resolution_of_HSL_from_RGB24<HSL192F>(); | |
cout | |
<< "HSL resolution from RGB24:\n" | |
" H: " << calculated_resolution.h << "\n" | |
" S: " << calculated_resolution.s << "\n" | |
" L: " << calculated_resolution.l << endl; | |
} catch (exception e) { | |
cerr << "oops! : " << e.what(); | |
} catch (...) { | |
cerr << "oops! : unknown exception"; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment