Skip to content

Instantly share code, notes, and snippets.

@usagi
Created January 14, 2013 09:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save usagi/4528935 to your computer and use it in GitHub Desktop.
Save usagi/4528935 to your computer and use it in GitHub Desktop.
#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