1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| namespace colorscale {
using uchar_t = unsigned char;
using color_t = std::array<uchar_t, 3>;
// First element is the abcissa, second is the direction
// Third element is the ordinate, 4th is the direction
// 5th tells if the last dimension must be set to 0 (false) or 255 (true)
using range_t = std::tuple<uchar_t, bool, uchar_t, bool, bool>;
using cube_8th_t = std::array<range_t, 3>;
color_t ComputeColorFromIndex(size_t index) {
// Defining constants data describing the RGB cube face parts
std::array<color_t, 8> const summits {{
{{0,0,0}}
, {{255,0,0}}
, {{255,255,0}}
, {{0,255,0}}
, {{0,0,255}}
, {{255,0,255}}
, {{255,255,255}}
, {{0,255,255}}
}};
std::array<cube_8th_t, 8> const faces_parts {{
{{ range_t(0,true,2,true, false), range_t(2,true,1,true,false), range_t(1,true,0,true,false) }}
, {{ range_t(1,true,2,true,true), range_t(2,true,0,false,false), range_t(0,false,1,true,false) }}
, {{ range_t(0,false,2,true,true), range_t(2,true, 1, false, true), range_t(1,false,0,false, false) }}
, {{ range_t(1,false,2,true,false), range_t(2,true,0,true,true), range_t(0,true,1,false,false) }}
, {{ range_t(2,false,0,true,false), range_t(0,true,1,true,true), range_t(1,true,2,false,false) }}
, {{ range_t(2,false,1,true,true), range_t(1,true,0,false,true), range_t(0,false,2,false,false) }}
, {{ range_t(2,false,0,false,true), range_t(0,false,1,false,true), range_t(1,false,2,false,true) }}
, {{ range_t(2,false,1,false,false), range_t(1,false,0,true,true), range_t(0,true,2,false,true) }}
}};
auto const choose_bucket = [](size_t i) -> size_t {
switch (i) {
case 0: return 2;
case 1: return 5;
case 2: return 0;
case 3: return 3;
case 4: return 6;
case 5: return 1;
case 6: return 4;
case 7:
default: return 7;
}
};
// This algorithm is limited to the external faces of the RGB cube
index %= (2*256*256 + 2*256*254 + 2*254*254);
// The first 3 bits choses the summit
size_t summit_index = index % 8;
index /= 8;
color_t result {{ 0, 0, 0 }};
if(0u == index) {
result = summits[summit_index];
}
else {
// Choose a face then normalize the index
--index;
size_t chosen_face_index = index % 3;
index /= 3;
// Extract x component and y component
size_t x_comp = index%128;
size_t y_comp = index/128;
// The following lines works for 128x127 zones but is not
// easily extendable to other dimensions
size_t x_coord = 16*choose_bucket(x_comp%8) + x_comp/8;
size_t y_coord = 16*choose_bucket(y_comp%8) + y_comp/8 + 1;
// Project that position on the given face
range_t const & face = faces_parts[summit_index][chosen_face_index];
result[std::get<0>(face)] = std::get<1>(face) ? x_coord : 255 - x_coord;
result[std::get<2>(face)] = std::get<3>(face) ? y_coord : 255 - y_coord;
// Finding the third axis
size_t sum = std::get<0>(face) + std::get<2>(face);
size_t third_axis = (1 == sum) ? 2u : ((2 == sum) ? 1u : 0u);
result[third_axis] = std::get<4>(face) ? 255u : 0u;
}
return result;
}
} // namespace colorscale |
Partager