Mercurial > hg > svgui
comparison layer/ColourScale.cpp @ 1146:74f2706995b7 3.0-integration
Merge work on unified spectrogram and colour 3d plot caching renderer
author | Chris Cannam |
---|---|
date | Fri, 05 Aug 2016 15:05:02 +0100 |
parents | c53ed1a6fcbd |
children | 822edd9bb665 |
comparison
equal
deleted
inserted
replaced
1056:b4fd6c67fce5 | 1146:74f2706995b7 |
---|---|
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-2016 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 "ColourScale.h" | |
17 | |
18 #include "base/AudioLevel.h" | |
19 #include "base/LogRange.h" | |
20 | |
21 #include <cmath> | |
22 #include <iostream> | |
23 | |
24 using namespace std; | |
25 | |
26 int ColourScale::m_maxPixel = 255; | |
27 | |
28 ColourScale::ColourScale(Parameters parameters) : | |
29 m_params(parameters), | |
30 m_mapper(m_params.colourMap, 1.f, double(m_maxPixel)) | |
31 { | |
32 if (m_params.minValue >= m_params.maxValue) { | |
33 cerr << "ERROR: ColourScale::ColourScale: minValue = " | |
34 << m_params.minValue << ", maxValue = " << m_params.maxValue << endl; | |
35 throw std::logic_error("maxValue must be greater than minValue"); | |
36 } | |
37 | |
38 m_mappedMin = m_params.minValue; | |
39 m_mappedMax = m_params.maxValue; | |
40 | |
41 if (m_mappedMin < m_params.threshold) { | |
42 m_mappedMin = m_params.threshold; | |
43 } | |
44 | |
45 if (m_params.scaleType == ColourScaleType::Log) { | |
46 | |
47 LogRange::mapRange(m_mappedMin, m_mappedMax); | |
48 | |
49 } else if (m_params.scaleType == ColourScaleType::PlusMinusOne) { | |
50 | |
51 m_mappedMin = -1.0; | |
52 m_mappedMax = 1.0; | |
53 | |
54 } else if (m_params.scaleType == ColourScaleType::Absolute) { | |
55 | |
56 m_mappedMin = fabs(m_mappedMin); | |
57 m_mappedMax = fabs(m_mappedMax); | |
58 if (m_mappedMin >= m_mappedMax) { | |
59 std::swap(m_mappedMin, m_mappedMax); | |
60 } | |
61 } | |
62 | |
63 if (m_mappedMin >= m_mappedMax) { | |
64 cerr << "ERROR: ColourScale::ColourScale: minValue = " << m_params.minValue | |
65 << ", maxValue = " << m_params.maxValue | |
66 << ", threshold = " << m_params.threshold | |
67 << ", scale = " << int(m_params.scaleType) | |
68 << " resulting in mapped minValue = " << m_mappedMin | |
69 << ", mapped maxValue = " << m_mappedMax << endl; | |
70 throw std::logic_error("maxValue must be greater than minValue [after mapping]"); | |
71 } | |
72 } | |
73 | |
74 ColourScale::~ColourScale() | |
75 { | |
76 } | |
77 | |
78 ColourScaleType | |
79 ColourScale::getScale() const | |
80 { | |
81 return m_params.scaleType; | |
82 } | |
83 | |
84 int | |
85 ColourScale::getPixel(double value) const | |
86 { | |
87 double maxPixF = m_maxPixel; | |
88 | |
89 if (m_params.scaleType == ColourScaleType::Phase) { | |
90 double half = (maxPixF - 1.f) / 2.f; | |
91 int pixel = 1 + int((value * half) / M_PI + half); | |
92 // cerr << "phase = " << value << " pixel = " << pixel << endl; | |
93 return pixel; | |
94 } | |
95 | |
96 value *= m_params.gain; | |
97 | |
98 if (value < m_params.threshold) return 0; | |
99 | |
100 double mapped = value; | |
101 | |
102 if (m_params.scaleType == ColourScaleType::Log) { | |
103 mapped = LogRange::map(value); | |
104 } else if (m_params.scaleType == ColourScaleType::PlusMinusOne) { | |
105 if (mapped < -1.f) mapped = -1.f; | |
106 if (mapped > 1.f) mapped = 1.f; | |
107 } else if (m_params.scaleType == ColourScaleType::Absolute) { | |
108 if (mapped < 0.f) mapped = -mapped; | |
109 } | |
110 | |
111 mapped *= m_params.multiple; | |
112 | |
113 if (mapped < m_mappedMin) { | |
114 mapped = m_mappedMin; | |
115 } | |
116 if (mapped > m_mappedMax) { | |
117 mapped = m_mappedMax; | |
118 } | |
119 | |
120 double proportion = (mapped - m_mappedMin) / (m_mappedMax - m_mappedMin); | |
121 | |
122 int pixel = 0; | |
123 | |
124 if (m_params.scaleType == ColourScaleType::Meter) { | |
125 pixel = AudioLevel::multiplier_to_preview(proportion, m_maxPixel-1) + 1; | |
126 } else { | |
127 pixel = int(proportion * maxPixF) + 1; | |
128 } | |
129 | |
130 if (pixel < 0) { | |
131 pixel = 0; | |
132 } | |
133 if (pixel > m_maxPixel) { | |
134 pixel = m_maxPixel; | |
135 } | |
136 return pixel; | |
137 } | |
138 | |
139 QColor | |
140 ColourScale::getColourForPixel(int pixel, int rotation) const | |
141 { | |
142 if (pixel < 0) { | |
143 pixel = 0; | |
144 } | |
145 if (pixel > m_maxPixel) { | |
146 pixel = m_maxPixel; | |
147 } | |
148 if (pixel == 0) { | |
149 if (m_mapper.hasLightBackground()) { | |
150 return Qt::white; | |
151 } else { | |
152 return Qt::black; | |
153 } | |
154 } else { | |
155 int target = int(pixel) + rotation; | |
156 while (target < 1) target += m_maxPixel; | |
157 while (target > m_maxPixel) target -= m_maxPixel; | |
158 return m_mapper.map(double(target)); | |
159 } | |
160 } |