aboutsummaryrefslogtreecommitdiff
path: root/colorscale.cpp
blob: f5afcbb281413bbb53a5f441f8723e946d8d98ba (plain)
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
88
#include "colorscale.h"

#include <cmath>

const float EPSILON = 1e-3f;

ColorScale::ColorScale(const QColor &firstColor, const QColor &lastColor)
    : m_colors{{firstColor, lastColor}}
{
    setExtents(0, 1);
}

ColorScale::ColorScale(std::initializer_list<QColor> colors)
    : m_colors(colors)
{
    setExtents(0, 1);
}

ColorScale::ColorScale(const QList<QColor> &colors)
    : m_colors(colors)
{
    setExtents(0, 1);
}

ColorScale::~ColorScale()
{
}

void ColorScale::setExtents(float min, float max)
{
    if (min >= max) {
        return;
    }

    m_min = min;
    m_max = max;
}

QColor ColorScale::lerp(const QColor &c1, const QColor &c2, float _t)
{
    qreal r1, g1, b1, a1;
    qreal r2, g2, b2, a2;
    qreal t = _t;

    c1.getRgbF(&r1, &g1, &b1, &a1);
    c2.getRgbF(&r2, &g2, &b2, &a2);
    QColor color;
    color.setRgbF(r1 * (1 - t) + r2 * t,
                  g1 * (1 - t) + g2 * t,
                  b1 * (1 - t) + b2 * t,
                  a1 * (1 - t) + a2 * t);
    return color;
}

QColor ColorScale::color(float t) const
{
    if (t < m_min || t > m_max) {
        return QColor();
    }

    // normalize t
    t = (t - m_min) / (m_max - m_min);

    // two colors, use a simpler solution
    if (m_colors.size() == 2) {
        return lerp(m_colors.first(), m_colors.last(), t);
    }

    if (fabs(t - m_min) < EPSILON) {
        return m_colors.first();
    }

    if (fabs(t - m_max) < EPSILON) {
        return m_colors.last();
    }

    // find which colors in the scale are adjacent to ours
    int i = int(t * m_colors.size());
    int j = i + 1;
    if (i >= m_colors.size() - 1) {
        return QColor(m_colors.last());
    }

    // normalize t between the two colors
    float step = 1.0f / m_colors.size();
    t = (t - i*step) / (j*step - i*step);
    return lerp(m_colors[i], m_colors[j], t);
}