comparison layer/ColourScale.cpp @ 1324:13d9b422f7fe zoom

Merge from default branch
author Chris Cannam
date Mon, 17 Sep 2018 13:51:31 +0100
parents a34a2a25907c
children d79e21855aef
comparison
equal deleted inserted replaced
1183:57d192e26331 1324:13d9b422f7fe
28 ColourScale::ColourScale(Parameters parameters) : 28 ColourScale::ColourScale(Parameters parameters) :
29 m_params(parameters), 29 m_params(parameters),
30 m_mapper(m_params.colourMap, 1.f, double(m_maxPixel)) 30 m_mapper(m_params.colourMap, 1.f, double(m_maxPixel))
31 { 31 {
32 if (m_params.minValue >= m_params.maxValue) { 32 if (m_params.minValue >= m_params.maxValue) {
33 cerr << "ERROR: ColourScale::ColourScale: minValue = " 33 SVCERR << "ERROR: ColourScale::ColourScale: minValue = "
34 << m_params.minValue << ", maxValue = " << m_params.maxValue << endl; 34 << m_params.minValue << ", maxValue = " << m_params.maxValue << endl;
35 throw std::logic_error("maxValue must be greater than minValue"); 35 throw std::logic_error("maxValue must be greater than minValue");
36 } 36 }
37 37
38 m_mappedMin = m_params.minValue; 38 m_mappedMin = m_params.minValue;
39 m_mappedMax = m_params.maxValue; 39 m_mappedMax = m_params.maxValue;
40 40
42 m_mappedMin = m_params.threshold; 42 m_mappedMin = m_params.threshold;
43 } 43 }
44 44
45 if (m_params.scaleType == ColourScaleType::Log) { 45 if (m_params.scaleType == ColourScaleType::Log) {
46 46
47 LogRange::mapRange(m_mappedMin, m_mappedMax); 47 // When used in e.g. spectrogram, we have a range with a min
48 48 // value of zero. The LogRange converts that to a threshold
49 // value of -10, so for a range of e.g. (0,1) we end up with
50 // (-10,0) as the mapped range.
51 //
52 // But in other contexts we could end up with a mapped range
53 // much larger than that if we have a small non-zero minimum
54 // value (less than 1e-10), or a particularly large
55 // maximum. That's unlikely to give us good results, so let's
56 // insist that the mapped log range has no more than 10
57 // difference between min and max, to match the behaviour when
58 // min == 0 at the input.
59 //
60 double threshold = -10.0;
61 LogRange::mapRange(m_mappedMin, m_mappedMax, threshold);
62 if (m_mappedMin < m_mappedMax + threshold) {
63 m_mappedMin = m_mappedMax + threshold;
64 }
65
49 } else if (m_params.scaleType == ColourScaleType::PlusMinusOne) { 66 } else if (m_params.scaleType == ColourScaleType::PlusMinusOne) {
50 67
51 m_mappedMin = -1.0; 68 m_mappedMin = -1.0;
52 m_mappedMax = 1.0; 69 m_mappedMax = 1.0;
53 70
54 } else if (m_params.scaleType == ColourScaleType::Absolute) { 71 } else if (m_params.scaleType == ColourScaleType::Absolute) {
55 72
56 m_mappedMin = fabs(m_mappedMin); 73 m_mappedMin = fabs(m_mappedMin);
57 m_mappedMax = fabs(m_mappedMax); 74 m_mappedMax = fabs(m_mappedMax);
58 if (m_mappedMin >= m_mappedMax) { 75 if (m_mappedMin >= m_mappedMax) {
59 std::swap(m_mappedMin, m_mappedMax); 76 std::swap(m_mappedMin, m_mappedMax);
60 } 77 }
61 } 78 }
62 79
63 if (m_mappedMin >= m_mappedMax) { 80 if (m_mappedMin >= m_mappedMax) {
64 cerr << "ERROR: ColourScale::ColourScale: minValue = " << m_params.minValue 81 SVCERR << "ERROR: ColourScale::ColourScale: minValue = " << m_params.minValue
65 << ", maxValue = " << m_params.maxValue 82 << ", maxValue = " << m_params.maxValue
66 << ", threshold = " << m_params.threshold 83 << ", threshold = " << m_params.threshold
67 << ", scale = " << int(m_params.scaleType) 84 << ", scale = " << int(m_params.scaleType)
68 << " resulting in mapped minValue = " << m_mappedMin 85 << " resulting in mapped minValue = " << m_mappedMin
69 << ", mapped maxValue = " << m_mappedMax << endl; 86 << ", mapped maxValue = " << m_mappedMax << endl;
70 throw std::logic_error("maxValue must be greater than minValue [after mapping]"); 87 throw std::logic_error("maxValue must be greater than minValue [after mapping]");
71 } 88 }
72 } 89 }
73 90
74 ColourScale::~ColourScale() 91 ColourScale::~ColourScale()
75 { 92 {
85 ColourScale::getPixel(double value) const 102 ColourScale::getPixel(double value) const
86 { 103 {
87 double maxPixF = m_maxPixel; 104 double maxPixF = m_maxPixel;
88 105
89 if (m_params.scaleType == ColourScaleType::Phase) { 106 if (m_params.scaleType == ColourScaleType::Phase) {
90 double half = (maxPixF - 1.f) / 2.f; 107 double half = (maxPixF - 1.f) / 2.f;
91 int pixel = 1 + int((value * half) / M_PI + half); 108 int pixel = 1 + int((value * half) / M_PI + half);
92 // cerr << "phase = " << value << " pixel = " << pixel << endl; 109 // SVCERR << "phase = " << value << " pixel = " << pixel << endl;
93 return pixel; 110 return pixel;
94 } 111 }
95 112
96 value *= m_params.gain; 113 value *= m_params.gain;
97 114
98 if (value < m_params.threshold) return 0; 115 if (value < m_params.threshold) return 0;
99 116
100 double mapped = value; 117 double mapped = value;
101 118
102 if (m_params.scaleType == ColourScaleType::Log) { 119 if (m_params.scaleType == ColourScaleType::Log) {
103 mapped = LogRange::map(value); 120 mapped = LogRange::map(value);
104 } else if (m_params.scaleType == ColourScaleType::PlusMinusOne) { 121 } else if (m_params.scaleType == ColourScaleType::PlusMinusOne) {
105 if (mapped < -1.f) mapped = -1.f; 122 if (mapped < -1.f) mapped = -1.f;
106 if (mapped > 1.f) mapped = 1.f; 123 if (mapped > 1.f) mapped = 1.f;
107 } else if (m_params.scaleType == ColourScaleType::Absolute) { 124 } else if (m_params.scaleType == ColourScaleType::Absolute) {
108 if (mapped < 0.f) mapped = -mapped; 125 if (mapped < 0.f) mapped = -mapped;
109 } 126 }
110 127
111 mapped *= m_params.multiple; 128 mapped *= m_params.multiple;
112 129
113 if (mapped < m_mappedMin) { 130 if (mapped < m_mappedMin) {
114 mapped = m_mappedMin; 131 mapped = m_mappedMin;
115 } 132 }
116 if (mapped > m_mappedMax) { 133 if (mapped > m_mappedMax) {
117 mapped = m_mappedMax; 134 mapped = m_mappedMax;
118 } 135 }
119 136
120 double proportion = (mapped - m_mappedMin) / (m_mappedMax - m_mappedMin); 137 double proportion = (mapped - m_mappedMin) / (m_mappedMax - m_mappedMin);
121 138
122 int pixel = 0; 139 int pixel = 0;
123 140
124 if (m_params.scaleType == ColourScaleType::Meter) { 141 if (m_params.scaleType == ColourScaleType::Meter) {
125 pixel = AudioLevel::multiplier_to_preview(proportion, m_maxPixel-1) + 1; 142 pixel = AudioLevel::multiplier_to_preview(proportion, m_maxPixel-1) + 1;
126 } else { 143 } else {
127 pixel = int(proportion * maxPixF) + 1; 144 pixel = int(proportion * maxPixF) + 1;
128 } 145 }
129 146
130 if (pixel < 0) { 147 if (pixel < 0) {
131 pixel = 0; 148 pixel = 0;
132 } 149 }
133 if (pixel > m_maxPixel) { 150 if (pixel > m_maxPixel) {
134 pixel = m_maxPixel; 151 pixel = m_maxPixel;
135 } 152 }
136 return pixel; 153 return pixel;
137 } 154 }
138 155
139 QColor 156 QColor
140 ColourScale::getColourForPixel(int pixel, int rotation) const 157 ColourScale::getColourForPixel(int pixel, int rotation) const
141 { 158 {
142 if (pixel < 0) { 159 if (pixel < 0) {
143 pixel = 0; 160 pixel = 0;
144 } 161 }
145 if (pixel > m_maxPixel) { 162 if (pixel > m_maxPixel) {
146 pixel = m_maxPixel; 163 pixel = m_maxPixel;
147 } 164 }
148 if (pixel == 0) { 165 if (pixel == 0) {
149 if (m_mapper.hasLightBackground()) { 166 if (m_mapper.hasLightBackground()) {
150 return Qt::white; 167 return Qt::white;
151 } else { 168 } else {
152 return Qt::black; 169 return Qt::black;
153 } 170 }
154 } else { 171 } else {
155 int target = int(pixel) + rotation; 172 int target = int(pixel) + rotation;
156 while (target < 1) target += m_maxPixel; 173 while (target < 1) target += m_maxPixel;
157 while (target > m_maxPixel) target -= m_maxPixel; 174 while (target > m_maxPixel) target -= m_maxPixel;
158 return m_mapper.map(double(target)); 175 return m_mapper.map(double(target));
159 } 176 }
160 } 177 }