8 float Palette::linearToPalette(
const float value)
const {
20 palette = float(
log10(value));
25 palette = 1.f + float(
log10(value));
26 }
else if (value < -1.f) {
27 palette = -1.f - float(
log10(-value));
39 float Palette::paletteToLinear(
const float value)
const {
44 return float(
exp10(value));
47 return float(
exp10(value - 1.f));
48 }
else if (value < -1.f) {
49 return float(-
exp10(-value - 1.f));
59 : points(other.points.clone())
61 , scale(other.scale) {}
71 : points(
std::move(controlPoints))
79 for (
Size i = 0; i < points.size() - 1; ++i) {
80 SPH_ASSERT(points[i].value < points[i + 1].value);
84 range =
Interval(points[0].value, points[points.size() - 1].value);
85 for (
Size i = 0; i < points.size(); ++i) {
86 points[i].value = linearToPalette(points[i].value);
96 Interval oldPaletteRange(points.front().value, points.back().value);
98 linearToPalette(
float(newRange.
lower())), linearToPalette(
float(newRange.
upper())));
99 const float scale = float(newPaletteRange.
size() / oldPaletteRange.
size());
100 const float offset = float(newPaletteRange.
lower() - scale * oldPaletteRange.
lower());
101 for (
Size i = 0; i < points.size(); ++i) {
102 points[i].value = points[i].value * scale + offset;
114 return points[0].color;
116 const float palette = linearToPalette(value);
117 if (palette <= points[0].value) {
118 return points[0].color;
120 if (palette >= points[points.size() - 1].value) {
121 return points[points.size() - 1].color;
123 for (
Size i = 0; i < points.size() - 1; ++i) {
124 if (
Interval(points[i].value, points[i + 1].value).contains(palette)) {
126 const float x = (points[i + 1].value - palette) / (points[i + 1].value - points[i].value);
127 return points[i].color * x + points[i + 1].color * (1.f - x);
135 for (
auto& point : cloned.points) {
136 point.color = func(point.color);
143 const float interpol = points[0].value * (1.f - value) + points.back().value * value;
148 return float(
exp10(interpol));
150 if (interpol > 1.f) {
151 return float(
exp10(interpol - 1.f));
152 }
else if (interpol < -1.f) {
153 return float(-
exp10(-interpol - 1.f));
163 const float linear = linearToPalette(value);
164 return (linear - points[0].value) / (points.back().value - points[0].value);
171 while (std::getline(ifs, line)) {
172 std::stringstream ss(
replaceAll(line,
",",
" "));
175 ss >> color.
r() >> color.
g() >> color.
b();
180 if (colors.
size() < 2) {
186 float from = points.front().value;
187 float to = points.back().value;
188 points.resize(colors.
size());
189 for (
Size i = 0; i < points.size(); ++i) {
190 points[i].color = colors[i];
192 points[i].value = from + float(i) * (to - from) / (points.size() - 1);
195 }
catch (
const std::exception& e) {
196 return makeFailed(
"Cannot load palette: ", e.what());
201 std::ifstream ifs(path.
native());
207 for (
Size i = 0; i < lineCnt; ++i) {
210 ofs << color.
r() <<
"," << color.
g() <<
"," << color.
b();
211 if (i != lineCnt - 1) {
216 }
catch (
const std::exception& e) {
217 return makeFailed(
"Cannot save palette: ", e.what());
222 std::ofstream os(path.
native());
INLINE bool isReal(const AntisymmetricTensor &t)
INLINE CopyableArray< T, TAllocator, TCounter > copyable(const Array< T, TAllocator, TCounter > &array)
#define SPH_ASSERT(x,...)
#define NOT_IMPLEMENTED
Helper macro marking missing implementation.
uint32_t Size
Integral type used to index arrays (by default).
INLINE T log10(const T f)
INLINE T exp10(const T f)
#define NAMESPACE_SPH_END
const SuccessTag SUCCESS
Global constant for successful outcome.
INLINE Outcome makeFailed(TArgs &&... args)
Constructs failed object with error message.
@ HYBRID
Logarithic scale for values > 1 and < -1, linear scale on interval <-1, 1>
@ LINEAR
Control points are interpolated on linear scale.
@ LOGARITHMIC
Control points are interpolated on logarithmic scale. All points must be positive!
Object representing a path on a filesystem, similar to std::filesystem::path in c++17.
std::string replaceAll(const std::string &source, const std::string &old, const std::string &s)
Replaces all occurences of string with a new string.
Generic dynamically allocated resizable storage.
INLINE void push(U &&u)
Adds new element to the end of the array, resizing the array if necessary.
INLINE TCounter size() const noexcept
Object representing a 1D interval of real numbers.
INLINE Float lower() const
Returns lower bound of the interval.
INLINE Float upper() const
Returns upper bound of the interval.
INLINE Float size() const
Returns the size of the interval.
Represents a color palette, used for mapping arbitrary number to a color.
void setInterval(const Interval &newRange)
Palette & operator=(const Palette &other)
float relativeToPalette(const float value) const
Converts a relative position to an absolute position on a palette.
PaletteScale getScale() const
Returns the scale of the palette.
Palette transform(Function< Rgba(const Rgba &)> func) const
Returns the palette with colors modified by generic transform.
Outcome saveToStream(std::ostream &ofs, const Size lineCnt=256) const
Saves the palettes into given output stream.
float paletteToRelative(const float value) const
Inverse transform to relativeToPalette.
Outcome loadFromFile(const Path &path)
Loads the palette from given .csv file.
Outcome loadFromStream(std::istream &ifs)
Loads the palette from given input stream.
Outcome saveToFile(const Path &path, const Size lineCnt=256) const
Saves the palette to a .csv file.
Rgba operator()(const float value) const
Returns the color mapped to given number.
Interval getInterval() const
Returns the interval for which the palette is defined.
Object representing a path on a filesystem.
std::string native() const
Returns the native version of the path.
Overload of std::swap for Sph::Array.