Chris@196
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@196
|
2
|
Chris@196
|
3 /*
|
Chris@196
|
4 Sonic Visualiser
|
Chris@196
|
5 An audio file viewer and annotation editor.
|
Chris@196
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@196
|
7 This file copyright 2006-2007 Chris Cannam and QMUL.
|
Chris@196
|
8
|
Chris@196
|
9 This program is free software; you can redistribute it and/or
|
Chris@196
|
10 modify it under the terms of the GNU General Public License as
|
Chris@196
|
11 published by the Free Software Foundation; either version 2 of the
|
Chris@196
|
12 License, or (at your option) any later version. See the file
|
Chris@196
|
13 COPYING included with this distribution for more information.
|
Chris@196
|
14 */
|
Chris@196
|
15
|
Chris@196
|
16 #include "ColourMapper.h"
|
Chris@196
|
17
|
Chris@197
|
18 #include <iostream>
|
Chris@197
|
19
|
Chris@196
|
20 ColourMapper::ColourMapper(int map, float min, float max) :
|
Chris@196
|
21 QObject(),
|
Chris@196
|
22 m_map(map),
|
Chris@196
|
23 m_min(min),
|
Chris@196
|
24 m_max(max)
|
Chris@196
|
25 {
|
Chris@197
|
26 if (m_min == m_max) {
|
Chris@197
|
27 std::cerr << "WARNING: ColourMapper: min == max (== " << m_min
|
Chris@197
|
28 << "), adjusting" << std::endl;
|
Chris@197
|
29 m_max = m_min + 1;
|
Chris@197
|
30 }
|
Chris@196
|
31 }
|
Chris@196
|
32
|
Chris@196
|
33 ColourMapper::~ColourMapper()
|
Chris@196
|
34 {
|
Chris@196
|
35 }
|
Chris@196
|
36
|
Chris@196
|
37 int
|
Chris@196
|
38 ColourMapper::getColourMapCount()
|
Chris@196
|
39 {
|
Chris@197
|
40 return 10;
|
Chris@196
|
41 }
|
Chris@196
|
42
|
Chris@196
|
43 QString
|
Chris@196
|
44 ColourMapper::getColourMapName(int n)
|
Chris@196
|
45 {
|
Chris@197
|
46 if (n >= getColourMapCount()) return tr("<unknown>");
|
Chris@196
|
47 StandardMap map = (StandardMap)n;
|
Chris@196
|
48
|
Chris@196
|
49 switch (map) {
|
Chris@196
|
50 case DefaultColours: return tr("Default");
|
Chris@196
|
51 case WhiteOnBlack: return tr("White on Black");
|
Chris@196
|
52 case BlackOnWhite: return tr("Black on White");
|
Chris@196
|
53 case RedOnBlue: return tr("Red on Blue");
|
Chris@196
|
54 case YellowOnBlack: return tr("Yellow on Black");
|
Chris@196
|
55 case BlueOnBlack: return tr("Blue on Black");
|
Chris@196
|
56 case Sunset: return tr("Sunset");
|
Chris@196
|
57 case FruitSalad: return tr("Fruit Salad");
|
Chris@197
|
58 case Banded: return tr("Banded");
|
Chris@197
|
59 case Highlight: return tr("Highlight");
|
Chris@196
|
60 }
|
Chris@196
|
61
|
Chris@196
|
62 return tr("<unknown>");
|
Chris@196
|
63 }
|
Chris@196
|
64
|
Chris@196
|
65 QColor
|
Chris@196
|
66 ColourMapper::map(float value) const
|
Chris@196
|
67 {
|
Chris@196
|
68 float norm = (value - m_min) / (m_max - m_min);
|
Chris@196
|
69 if (norm < 0.f) norm = 0.f;
|
Chris@196
|
70 if (norm > 1.f) norm = 1.f;
|
Chris@196
|
71
|
Chris@196
|
72 float h = 0.f, s = 0.f, v = 0.f, r = 0.f, g = 0.f, b = 0.f;
|
Chris@196
|
73 bool hsv = true;
|
Chris@196
|
74
|
Chris@196
|
75 float red = 0.f, green = 0.3333f, blue = 0.6666f, pieslice = 0.3333f;
|
Chris@196
|
76
|
Chris@197
|
77 if (m_map >= getColourMapCount()) return Qt::black;
|
Chris@196
|
78 StandardMap map = (StandardMap)m_map;
|
Chris@196
|
79
|
Chris@196
|
80 switch (map) {
|
Chris@196
|
81
|
Chris@196
|
82 case DefaultColours:
|
Chris@196
|
83 h = blue - norm * 2.f * pieslice;
|
Chris@196
|
84 s = 0.5f + norm/2.f;
|
Chris@196
|
85 v = norm;
|
Chris@196
|
86 break;
|
Chris@196
|
87
|
Chris@196
|
88 case WhiteOnBlack:
|
Chris@196
|
89 r = g = b = norm;
|
Chris@196
|
90 hsv = false;
|
Chris@196
|
91 break;
|
Chris@196
|
92
|
Chris@196
|
93 case BlackOnWhite:
|
Chris@196
|
94 r = g = b = 1.f - norm;
|
Chris@196
|
95 hsv = false;
|
Chris@196
|
96 break;
|
Chris@196
|
97
|
Chris@196
|
98 case RedOnBlue:
|
Chris@196
|
99 h = blue - pieslice/4.f + norm * (pieslice + pieslice/4.f);
|
Chris@196
|
100 s = 1.f;
|
Chris@196
|
101 v = norm;
|
Chris@196
|
102 break;
|
Chris@196
|
103
|
Chris@196
|
104 case YellowOnBlack:
|
Chris@196
|
105 h = 0.15f;
|
Chris@196
|
106 s = 1.f;
|
Chris@196
|
107 v = norm;
|
Chris@196
|
108 break;
|
Chris@196
|
109
|
Chris@196
|
110 case BlueOnBlack:
|
Chris@197
|
111 h = blue;
|
Chris@196
|
112 s = 1.f;
|
Chris@196
|
113 v = norm * 2.f;
|
Chris@197
|
114 if (v > 1.f) {
|
Chris@196
|
115 v = 1.f;
|
Chris@197
|
116 s = 1.f - (sqrtf(norm) - 0.707f) * 3.413f;
|
Chris@197
|
117 if (s < 0.f) s = 0.f;
|
Chris@197
|
118 if (s > 1.f) s = 1.f;
|
Chris@196
|
119 }
|
Chris@196
|
120 break;
|
Chris@196
|
121
|
Chris@196
|
122 case Sunset:
|
Chris@196
|
123 r = (norm - 0.24f) * 2.38f;
|
Chris@196
|
124 if (r > 1.f) r = 1.f;
|
Chris@196
|
125 if (r < 0.f) r = 0.f;
|
Chris@196
|
126 g = (norm - 0.64f) * 2.777f;
|
Chris@196
|
127 if (g > 1.f) g = 1.f;
|
Chris@196
|
128 if (g < 0.f) g = 0.f;
|
Chris@196
|
129 b = (3.6f * norm);
|
Chris@196
|
130 if (norm > 0.277f) b = 2.f - b;
|
Chris@196
|
131 if (b > 1.f) b = 1.f;
|
Chris@196
|
132 if (b < 0.f) b = 0.f;
|
Chris@196
|
133 hsv = false;
|
Chris@196
|
134 break;
|
Chris@196
|
135
|
Chris@196
|
136 case FruitSalad:
|
Chris@197
|
137 h = blue + (pieslice/6.f) - norm;
|
Chris@196
|
138 if (h < 0.f) h += 1.f;
|
Chris@196
|
139 s = 1.f;
|
Chris@196
|
140 v = 1.f;
|
Chris@196
|
141 break;
|
Chris@197
|
142
|
Chris@197
|
143 case Banded:
|
Chris@197
|
144 if (norm < 0.125) return Qt::darkGreen;
|
Chris@197
|
145 else if (norm < 0.25) return Qt::green;
|
Chris@197
|
146 else if (norm < 0.375) return Qt::darkBlue;
|
Chris@197
|
147 else if (norm < 0.5) return Qt::blue;
|
Chris@197
|
148 else if (norm < 0.625) return Qt::darkYellow;
|
Chris@197
|
149 else if (norm < 0.75) return Qt::yellow;
|
Chris@197
|
150 else if (norm < 0.875) return Qt::darkRed;
|
Chris@197
|
151 else return Qt::red;
|
Chris@197
|
152 break;
|
Chris@197
|
153
|
Chris@197
|
154 case Highlight:
|
Chris@197
|
155 if (norm > 0.99) return Qt::white;
|
Chris@197
|
156 else return Qt::darkBlue;
|
Chris@196
|
157 }
|
Chris@196
|
158
|
Chris@196
|
159 if (hsv) {
|
Chris@196
|
160 return QColor::fromHsvF(h, s, v);
|
Chris@196
|
161 } else {
|
Chris@196
|
162 return QColor::fromRgbF(r, g, b);
|
Chris@196
|
163 }
|
Chris@196
|
164 }
|
Chris@196
|
165
|
Chris@196
|
166 QColor
|
Chris@196
|
167 ColourMapper::getContrastingColour() const
|
Chris@196
|
168 {
|
Chris@197
|
169 if (m_map >= getColourMapCount()) return Qt::white;
|
Chris@196
|
170 StandardMap map = (StandardMap)m_map;
|
Chris@196
|
171
|
Chris@196
|
172 switch (map) {
|
Chris@196
|
173
|
Chris@196
|
174 case DefaultColours:
|
Chris@196
|
175 return QColor(255, 150, 50);
|
Chris@196
|
176
|
Chris@196
|
177 case WhiteOnBlack:
|
Chris@196
|
178 return Qt::red;
|
Chris@196
|
179
|
Chris@196
|
180 case BlackOnWhite:
|
Chris@196
|
181 return Qt::darkGreen;
|
Chris@196
|
182
|
Chris@196
|
183 case RedOnBlue:
|
Chris@196
|
184 return Qt::green;
|
Chris@196
|
185
|
Chris@196
|
186 case YellowOnBlack:
|
Chris@196
|
187 return QColor::fromHsv(240, 255, 255);
|
Chris@196
|
188
|
Chris@196
|
189 case BlueOnBlack:
|
Chris@196
|
190 return Qt::red;
|
Chris@196
|
191
|
Chris@196
|
192 case Sunset:
|
Chris@196
|
193 return Qt::white;
|
Chris@196
|
194
|
Chris@196
|
195 case FruitSalad:
|
Chris@196
|
196 return Qt::white;
|
Chris@197
|
197
|
Chris@197
|
198 case Banded:
|
Chris@197
|
199 return Qt::cyan;
|
Chris@197
|
200
|
Chris@197
|
201 case Highlight:
|
Chris@197
|
202 return Qt::red;
|
Chris@196
|
203 }
|
Chris@196
|
204
|
Chris@196
|
205 return Qt::white;
|
Chris@196
|
206 }
|
Chris@196
|
207
|
Chris@196
|
208
|