svgui  1.9
ColourMapper.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7  This file copyright 2006-2007 Chris Cannam and QMUL.
8 
9  This program is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 2 of the
12  License, or (at your option) any later version. See the file
13  COPYING included with this distribution for more information.
14 */
15 
16 #include "ColourMapper.h"
17 
18 #include <iostream>
19 
20 #include <cmath>
21 
22 #include "base/Debug.h"
23 
24 ColourMapper::ColourMapper(int map, float min, float max) :
25  QObject(),
26  m_map(map),
27  m_min(min),
28  m_max(max)
29 {
30  if (m_min == m_max) {
31  cerr << "WARNING: ColourMapper: min == max (== " << m_min
32  << "), adjusting" << endl;
33  m_max = m_min + 1;
34  }
35 }
36 
38 {
39 }
40 
41 int
43 {
44  return 12;
45 }
46 
47 QString
49 {
50  if (n >= getColourMapCount()) return tr("<unknown>");
52 
53  switch (map) {
54  case DefaultColours: return tr("Default");
55  case WhiteOnBlack: return tr("White on Black");
56  case BlackOnWhite: return tr("Black on White");
57  case RedOnBlue: return tr("Red on Blue");
58  case YellowOnBlack: return tr("Yellow on Black");
59  case BlueOnBlack: return tr("Blue on Black");
60  case Sunset: return tr("Sunset");
61  case FruitSalad: return tr("Fruit Salad");
62  case Banded: return tr("Banded");
63  case Highlight: return tr("Highlight");
64  case Printer: return tr("Printer");
65  case HighGain: return tr("High Gain");
66  }
67 
68  return tr("<unknown>");
69 }
70 
71 QColor
72 ColourMapper::map(float value) const
73 {
74  float norm = (value - m_min) / (m_max - m_min);
75  if (norm < 0.f) norm = 0.f;
76  if (norm > 1.f) norm = 1.f;
77 
78  float h = 0.f, s = 0.f, v = 0.f, r = 0.f, g = 0.f, b = 0.f;
79  bool hsv = true;
80 
81 // float red = 0.f, green = 0.3333f;
82  float blue = 0.6666f, pieslice = 0.3333f;
83 
84  if (m_map >= getColourMapCount()) return Qt::black;
86 
87  switch (map) {
88 
89  case DefaultColours:
90  h = blue - norm * 2.f * pieslice;
91  s = 0.5f + norm/2.f;
92  v = norm;
93  break;
94 
95  case WhiteOnBlack:
96  r = g = b = norm;
97  hsv = false;
98  break;
99 
100  case BlackOnWhite:
101  r = g = b = 1.f - norm;
102  hsv = false;
103  break;
104 
105  case RedOnBlue:
106  h = blue - pieslice/4.f + norm * (pieslice + pieslice/4.f);
107  s = 1.f;
108  v = norm;
109  break;
110 
111  case YellowOnBlack:
112  h = 0.15f;
113  s = 1.f;
114  v = norm;
115  break;
116 
117  case BlueOnBlack:
118  h = blue;
119  s = 1.f;
120  v = norm * 2.f;
121  if (v > 1.f) {
122  v = 1.f;
123  s = 1.f - (sqrtf(norm) - 0.707f) * 3.413f;
124  if (s < 0.f) s = 0.f;
125  if (s > 1.f) s = 1.f;
126  }
127  break;
128 
129  case Sunset:
130  r = (norm - 0.24f) * 2.38f;
131  if (r > 1.f) r = 1.f;
132  if (r < 0.f) r = 0.f;
133  g = (norm - 0.64f) * 2.777f;
134  if (g > 1.f) g = 1.f;
135  if (g < 0.f) g = 0.f;
136  b = (3.6f * norm);
137  if (norm > 0.277f) b = 2.f - b;
138  if (b > 1.f) b = 1.f;
139  if (b < 0.f) b = 0.f;
140  hsv = false;
141  break;
142 
143  case FruitSalad:
144  h = blue + (pieslice/6.f) - norm;
145  if (h < 0.f) h += 1.f;
146  s = 1.f;
147  v = 1.f;
148  break;
149 
150  case Banded:
151  if (norm < 0.125) return Qt::darkGreen;
152  else if (norm < 0.25) return Qt::green;
153  else if (norm < 0.375) return Qt::darkBlue;
154  else if (norm < 0.5) return Qt::blue;
155  else if (norm < 0.625) return Qt::darkYellow;
156  else if (norm < 0.75) return Qt::yellow;
157  else if (norm < 0.875) return Qt::darkRed;
158  else return Qt::red;
159  break;
160 
161  case Highlight:
162  if (norm > 0.99) return Qt::white;
163  else return Qt::darkBlue;
164 
165  case Printer:
166  if (norm > 0.8) {
167  r = 1.f;
168  } else if (norm > 0.7) {
169  r = 0.9f;
170  } else if (norm > 0.6) {
171  r = 0.8f;
172  } else if (norm > 0.5) {
173  r = 0.7f;
174  } else if (norm > 0.4) {
175  r = 0.6f;
176  } else if (norm > 0.3) {
177  r = 0.5f;
178  } else if (norm > 0.2) {
179  r = 0.4f;
180  } else {
181  r = 0.f;
182  }
183  r = g = b = 1.f - r;
184  hsv = false;
185  break;
186 
187  case HighGain:
188  if (norm <= 1.f / 256.f) {
189  norm = 0.f;
190  } else {
191  norm = 0.1f + (powf(((norm - 0.5f) * 2.f), 3.f) + 1.f) / 2.081f;
192  }
193  // now as for Sunset
194  r = (norm - 0.24f) * 2.38f;
195  if (r > 1.f) r = 1.f;
196  if (r < 0.f) r = 0.f;
197  g = (norm - 0.64f) * 2.777f;
198  if (g > 1.f) g = 1.f;
199  if (g < 0.f) g = 0.f;
200  b = (3.6f * norm);
201  if (norm > 0.277f) b = 2.f - b;
202  if (b > 1.f) b = 1.f;
203  if (b < 0.f) b = 0.f;
204  hsv = false;
205 /*
206  if (r > 1.f) r = 1.f;
207  r = g = b = 1.f - r;
208  hsv = false;
209 */
210  break;
211  }
212 
213  if (hsv) {
214  return QColor::fromHsvF(h, s, v);
215  } else {
216  return QColor::fromRgbF(r, g, b);
217  }
218 }
219 
220 QColor
222 {
223  if (m_map >= getColourMapCount()) return Qt::white;
225 
226  switch (map) {
227 
228  case DefaultColours:
229  return QColor(255, 150, 50);
230 
231  case WhiteOnBlack:
232  return Qt::red;
233 
234  case BlackOnWhite:
235  return Qt::darkGreen;
236 
237  case RedOnBlue:
238  return Qt::green;
239 
240  case YellowOnBlack:
241  return QColor::fromHsv(240, 255, 255);
242 
243  case BlueOnBlack:
244  return Qt::red;
245 
246  case Sunset:
247  return Qt::white;
248 
249  case FruitSalad:
250  return Qt::white;
251 
252  case Banded:
253  return Qt::cyan;
254 
255  case Highlight:
256  return Qt::red;
257 
258  case Printer:
259  return Qt::red;
260 
261  case HighGain:
262  return Qt::red;
263  }
264 
265  return Qt::white;
266 }
267 
268 bool
270 {
271  if (m_map >= getColourMapCount()) return false;
273 
274  switch (map) {
275 
276  case BlackOnWhite:
277  case Printer:
278  case HighGain:
279  return true;
280 
281  case DefaultColours:
282  case Sunset:
283  case WhiteOnBlack:
284  case RedOnBlue:
285  case YellowOnBlack:
286  case BlueOnBlack:
287  case FruitSalad:
288  case Banded:
289  case Highlight:
290 
291  default:
292  return false;
293  }
294 }
295 
296 
static int getColourMapCount()
virtual ~ColourMapper()
QColor map(float value) const
QColor getContrastingColour() const
ColourMapper(int map, float minValue, float maxValue)
bool hasLightBackground() const
static QString getColourMapName(int n)