comparison layer/ColourScale.cpp @ 1068:521f7e8b0559 spectrogram-minor-refactor

Introduce ColourScale to handle colour mapping for both spectrogram and colour 3d plot layers
author Chris Cannam
date Thu, 23 Jun 2016 14:42:37 +0100
parents
children 27163db978d8
comparison
equal deleted inserted replaced
1067:6eb9e032e708 1068:521f7e8b0559
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
23 int ColourScale::m_maxPixel = 255;
24
25 ColourScale::ColourScale(int colourMap,
26 Scale scale,
27 double minValue,
28 double maxValue,
29 double threshold,
30 double gain) :
31 m_mapper(colourMap, 1.f, double(m_maxPixel)),
32 m_scale(scale),
33 m_min(minValue),
34 m_max(maxValue),
35 m_threshold(threshold),
36 m_gain(gain)
37 {
38 if (minValue >= maxValue) {
39 throw std::logic_error("maxValue must be greater than minValue");
40 }
41
42 m_mappedMin = m_min;
43 m_mappedMax = m_max;
44
45 if (m_scale == LogColourScale) {
46
47 LogRange::mapRange(m_mappedMin, m_mappedMax);
48
49 } else if (m_scale == PlusMinusOneScale) {
50
51 m_mappedMin = -1.0;
52 m_mappedMax = 1.0;
53
54 } else if (m_scale == AbsoluteScale) {
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 throw std::logic_error("maxValue must be greater than minValue [after mapping]");
65 }
66 }
67
68 int
69 ColourScale::getPixel(double value)
70 {
71 double maxPixF = m_maxPixel;
72
73 if (m_scale == PhaseColourScale) {
74 double half = (maxPixF - 1.f) / 2.f;
75 return 1 + int((value * half) / M_PI + half);
76 }
77
78 value *= m_gain;
79
80 if (value < m_threshold) return 0;
81
82 double mapped = value;
83
84 if (m_scale == LogColourScale) {
85 mapped = LogRange::map(value);
86 } else if (m_scale == PlusMinusOneScale) {
87 if (mapped < -1.f) mapped = -1.f;
88 if (mapped > 1.f) mapped = 1.f;
89 } else if (m_scale == AbsoluteScale) {
90 if (mapped < 0.f) mapped = -mapped;
91 }
92
93 if (mapped < m_mappedMin) {
94 mapped = m_mappedMin;
95 }
96 if (mapped > m_mappedMax) {
97 mapped = m_mappedMax;
98 }
99
100 double proportion = (mapped - m_mappedMin) / (m_mappedMax - m_mappedMin);
101
102 int pixel = 0;
103
104 if (m_scale == MeterColourScale) {
105 pixel = AudioLevel::multiplier_to_preview(proportion, m_maxPixel-1) + 1;
106 } else {
107 pixel = int(proportion * maxPixF) + 1;
108 }
109
110 if (pixel > m_maxPixel) pixel = m_maxPixel;
111 if (pixel < 0) pixel = 0;
112 return pixel;
113 }
114
115 QColor
116 ColourScale::getColourForPixel(int pixel, int rotation)
117 {
118 if (pixel < 0) {
119 pixel = 0;
120 }
121 if (pixel > m_maxPixel) {
122 pixel = m_maxPixel;
123 }
124 if (pixel == 0) {
125 if (m_mapper.hasLightBackground()) {
126 return Qt::white;
127 } else {
128 return Qt::black;
129 }
130 } else {
131 int target = int(pixel) + rotation;
132 while (target < 1) target += m_maxPixel;
133 while (target > m_maxPixel) target -= m_maxPixel;
134 return m_mapper.map(double(target));
135 }
136 }