1#include "color_scale.h"
11color<float,RGB> color_scale(
double v, ColorScale cs,
int polarity)
14 case CS_RED:
return color<float, RGB>((
float)v, 0, 0);
15 case CS_GREEN:
return color<float, RGB>(0, (
float)v, 0);
16 case CS_BLUE:
return color<float, RGB>(0, 0, (
float)v);
17 case CS_GRAY:
return color<float, RGB>((
float)v, (
float)v, (
float)v);
20 return color<float, RGB>((
float)(3 * v), 0, 0);
22 return color<float, RGB>(1, (
float)(3 * v) - 1, 0);
23 return color<float, RGB>(1, 1, (
float)(3 * v) - 2);
25 return color<float, RGB>(color<float, HLS>((
float)v, 0.5f, 1));
26 case CS_HUE_LUMINANCE:
27 return color<float, RGB>(color<float, HLS>((
float)v, (
float)(0.5 * v + 0.25), 1));
29 if (
int(cs - CS_NAMED) < query_color_scale_names(polarity).size())
30 return sample_sampled_color_scale((
float)v, query_named_color_scale(query_color_scale_names(polarity)[cs - CS_NAMED]));
33 return color<float,RGB>((
float)v, (
float)v, (
float)v);
36double color_scale_gamma_mapping(
double v,
double gamma,
bool is_bipolar,
double window_zero_position)
39 double amplitude = std::max(window_zero_position, 1.0 - window_zero_position);
40 if (v < window_zero_position)
41 return window_zero_position - std::pow((window_zero_position - v) / amplitude, gamma) * amplitude;
43 return std::pow((v - window_zero_position) / amplitude, gamma) * amplitude + window_zero_position;
46 return std::pow(v, gamma);
50double adjust_zero_position(
double v,
double window_zero_position)
52 if (window_zero_position <= 0.5)
53 return 1.0 - 0.5 * (1.0 - v) / (1.0 - window_zero_position);
55 return 0.5 * v / window_zero_position;
58typedef std::pair<std::vector<color<float, RGB>>,
bool> scs_entry_type;
59typedef std::map<std::string, scs_entry_type> scs_map_type;
61std::vector<color<float, RGB>> construct_sampled_color_scale(
unsigned count,
unsigned* data)
63 ::std::vector<color<float, RGB>> samples;
64 for (
unsigned i = 0; i < count; ++i)
65 samples.push_back(color<float, RGB>(((data[i] & 0xff0000) >> 16) / 255.0f, ((data[i] & 0xff00) >> 8) / 255.0f, (data[i] & 0xff) / 255.0f));
69scs_map_type& ref_sampled_color_scale_map()
71 static scs_map_type scs_map;
72 static bool initialized =
false;
76 static unsigned temp[11] = { 0x000000,0x3b0000,0x760000,0xba0000,0xff0000,0xff5300,0xffa500,0xfbce12,0xf7f825,0xfbfc92,0xffffff };
78 static unsigned anag[9] = { 0x000000,0x32172e,0x5d2851,0x873e6f,0xaf5c85,0xd37e93,0xefa79b,0xffd4a4,0xffffff };
80 static unsigned bipo[8] = { 0x43ffff, 0x00cdcd, 0x0073ff, 0x203434, 0x332420, 0xac0000, 0xff6100, 0xffe000 };
82 static unsigned hue[7] = { 0xff0000,0xffff00,0x00ff00,0x00ffff,0x0000ff,0xff00ff,0xff0000 };
83 scs_map[
"temperature_11"] = scs_entry_type(construct_sampled_color_scale(11, temp),
false);
84 scs_map[
"anaglyph_9"] = scs_entry_type(construct_sampled_color_scale(9, anag),
false);
85 scs_map[
"bipolar_8"] = scs_entry_type(construct_sampled_color_scale(8, bipo),
true);
86 scs_map[
"hue_7"] = scs_entry_type(construct_sampled_color_scale(7, hue),
false);
92size_t& ref_named_color_scale_timestamp()
94 static size_t timestamp = 1;
98size_t get_named_color_scale_timestamp()
100 return ref_named_color_scale_timestamp();
103void register_named_color_scale(
const std::string& name,
const std::vector<color<float, RGB>>& samples,
bool is_bipolar)
105 ref_sampled_color_scale_map()[name] = scs_entry_type(samples, is_bipolar);
106 ++ref_named_color_scale_timestamp();
109const std::vector<std::string>& query_color_scale_names(
int polarity)
111 static std::vector<std::string> names[3];
112 static size_t timestamp[3] = { 0, 0, 0 };
113 if (timestamp[polarity] < get_named_color_scale_timestamp()) {
114 for (
const auto& p : ref_sampled_color_scale_map())
115 if (polarity == 0 || (polarity == (p.second.second ? 2 : 1)))
116 names[polarity].push_back(p.first);
117 timestamp[polarity] = get_named_color_scale_timestamp();
119 return names[polarity];
122std::string get_color_scale_name(ColorScale cs)
124 static const char* color_scale_names[] = {
"red",
"green",
"blue",
"gray",
"temperature",
"hue",
"hue_luminance" };
126 return color_scale_names[cs];
127 int idx = cs - CS_NAMED;
128 if (idx < ref_sampled_color_scale_map().size())
129 for (
const auto& p : ref_sampled_color_scale_map()) {
134 return std::string();
137bool find_color_scale(
const std::string& name, ColorScale& cs)
139 const auto& csm = ref_sampled_color_scale_map();
140 if (csm.find(name) != csm.end()) {
141 ColorScale _cs = CS_NAMED;
142 for (
const auto& p : csm) {
143 if (p.first == name) {
154 else if (lname ==
"green")
156 else if (lname ==
"blue")
158 else if (lname ==
"gray")
160 else if (lname ==
"temperature")
162 else if (lname ==
"hue")
164 else if (lname ==
"hue_luminance")
165 cs = CS_HUE_LUMINANCE;
171const std::string& get_color_scale_enum_definition(
bool include_fixed,
bool include_named,
int polarity)
173 static std::string empty =
"enums=''";
174 if (!include_fixed && !include_named)
176 unsigned i = (include_fixed ? 1 : 0) + (include_named ? 2 : 0) - 1 + 3*polarity;
177 static std::string enum_definitions[9];
178 static size_t timestamps[9] = { 0,0,0, 0,0,0, 0,0,0 };
179 if (timestamps[i] < get_named_color_scale_timestamp()) {
180 std::string def =
"enums='";
182 def +=
"red,green,blue,gray,temperature,hue,hue_luminance";
184 bool no_comma = !include_fixed;
186 for (
const auto& p : ref_sampled_color_scale_map()) {
187 if (polarity == 0 || (polarity == (p.second.second ? 2 : 1))) {
200 enum_definitions[i] = def;
201 timestamps[i] = get_named_color_scale_timestamp();
203 return enum_definitions[i];
207const std::vector<color<float, RGB>>& query_named_color_scale(
const std::string& name,
bool* is_bipolar_ptr)
209 const auto& scs = ref_sampled_color_scale_map()[name];
211 *is_bipolar_ptr = scs.second;
215::std::vector<color<float, RGB>> sample_named_color_scale(
const std::string& name,
size_t nr_samples,
bool exact)
217 const auto& scs_map = ref_sampled_color_scale_map();
218 auto it = scs_map.find(name);
219 if (it == scs_map.end())
220 return ::std::vector<color<float, RGB>>();
222 return it->second.first;
224 size_t size = it->second.first.size();
225 size_t target_size = nr_samples;
229 if (nr_samples > size)
231 target_size = size * size_t(ceil(
double(nr_samples) / size));
234 size_t divisor = size_t(ceil(
double(size) / nr_samples));
235 while (divisor > 1) {
236 if (size == divisor * (size / divisor))
240 target_size = divisor * (size / divisor);
244 ::std::vector<color<float, RGB>> result(target_size);
245 for (
size_t i = 0; i < target_size; ++i) {
246 float value = float(i) / (target_size - 1);
247 result.push_back(sample_sampled_color_scale(value, it->second.first, it->second.second));
252color<float, RGB> sample_sampled_color_scale(
float value, const ::std::vector<color<float, RGB>>& samples,
bool is_bipolar)
256 return samples.front();
258 if (value > 0.99999f)
259 return samples.back();
263 if (is_bipolar && ((samples.size() & 1) == 0)) {
265 v = value * (samples.size() - 2);
269 if (i+1 >= samples.size()/2)
276 v = value * (samples.size() - 1);
283 return (1.0f - f) * samples[i] + f * samples[i + 1];
Helper functions to convert numeric types into strings using std streams.
std::string to_string(const std::string &v, unsigned int w, unsigned int p, bool)
specialization of conversion from string to strings
char to_lower(char c)
convert char to lower case
Helper functions to process strings.