annotate layer/ColourScale.cpp @ 1204:d421df27e184 3.0-integration

Further PropertyBox layout overhaul: avoid crash (/ assertion failure) when property type changes from e.g. colour to colourmap, by replacing the existing widget within the layout rather than trying to repopulate it
author Chris Cannam
date Tue, 20 Dec 2016 10:49:24 +0000
parents c53ed1a6fcbd
children 822edd9bb665
rev   line source
Chris@1068 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@1068 2
Chris@1068 3 /*
Chris@1068 4 Sonic Visualiser
Chris@1068 5 An audio file viewer and annotation editor.
Chris@1068 6 Centre for Digital Music, Queen Mary, University of London.
Chris@1068 7 This file copyright 2006-2016 Chris Cannam and QMUL.
Chris@1068 8
Chris@1068 9 This program is free software; you can redistribute it and/or
Chris@1068 10 modify it under the terms of the GNU General Public License as
Chris@1068 11 published by the Free Software Foundation; either version 2 of the
Chris@1068 12 License, or (at your option) any later version. See the file
Chris@1068 13 COPYING included with this distribution for more information.
Chris@1068 14 */
Chris@1068 15
Chris@1068 16 #include "ColourScale.h"
Chris@1068 17
Chris@1068 18 #include "base/AudioLevel.h"
Chris@1068 19 #include "base/LogRange.h"
Chris@1068 20
Chris@1068 21 #include <cmath>
Chris@1129 22 #include <iostream>
Chris@1129 23
Chris@1129 24 using namespace std;
Chris@1068 25
Chris@1068 26 int ColourScale::m_maxPixel = 255;
Chris@1068 27
Chris@1070 28 ColourScale::ColourScale(Parameters parameters) :
Chris@1070 29 m_params(parameters),
Chris@1070 30 m_mapper(m_params.colourMap, 1.f, double(m_maxPixel))
Chris@1068 31 {
Chris@1070 32 if (m_params.minValue >= m_params.maxValue) {
Chris@1129 33 cerr << "ERROR: ColourScale::ColourScale: minValue = "
Chris@1129 34 << m_params.minValue << ", maxValue = " << m_params.maxValue << endl;
Chris@1068 35 throw std::logic_error("maxValue must be greater than minValue");
Chris@1068 36 }
Chris@1068 37
Chris@1070 38 m_mappedMin = m_params.minValue;
Chris@1070 39 m_mappedMax = m_params.maxValue;
Chris@1068 40
Chris@1127 41 if (m_mappedMin < m_params.threshold) {
Chris@1127 42 m_mappedMin = m_params.threshold;
Chris@1127 43 }
Chris@1127 44
Chris@1137 45 if (m_params.scaleType == ColourScaleType::Log) {
Chris@1068 46
Chris@1068 47 LogRange::mapRange(m_mappedMin, m_mappedMax);
Chris@1068 48
Chris@1137 49 } else if (m_params.scaleType == ColourScaleType::PlusMinusOne) {
Chris@1068 50
Chris@1068 51 m_mappedMin = -1.0;
Chris@1068 52 m_mappedMax = 1.0;
Chris@1068 53
Chris@1137 54 } else if (m_params.scaleType == ColourScaleType::Absolute) {
Chris@1068 55
Chris@1068 56 m_mappedMin = fabs(m_mappedMin);
Chris@1068 57 m_mappedMax = fabs(m_mappedMax);
Chris@1068 58 if (m_mappedMin >= m_mappedMax) {
Chris@1068 59 std::swap(m_mappedMin, m_mappedMax);
Chris@1068 60 }
Chris@1068 61 }
Chris@1068 62
Chris@1068 63 if (m_mappedMin >= m_mappedMax) {
Chris@1129 64 cerr << "ERROR: ColourScale::ColourScale: minValue = " << m_params.minValue
Chris@1129 65 << ", maxValue = " << m_params.maxValue
Chris@1129 66 << ", threshold = " << m_params.threshold
Chris@1137 67 << ", scale = " << int(m_params.scaleType)
Chris@1129 68 << " resulting in mapped minValue = " << m_mappedMin
Chris@1129 69 << ", mapped maxValue = " << m_mappedMax << endl;
Chris@1068 70 throw std::logic_error("maxValue must be greater than minValue [after mapping]");
Chris@1068 71 }
Chris@1068 72 }
Chris@1068 73
Chris@1071 74 ColourScale::~ColourScale()
Chris@1071 75 {
Chris@1071 76 }
Chris@1071 77
Chris@1105 78 ColourScaleType
Chris@1079 79 ColourScale::getScale() const
Chris@1079 80 {
Chris@1137 81 return m_params.scaleType;
Chris@1079 82 }
Chris@1079 83
Chris@1068 84 int
Chris@1079 85 ColourScale::getPixel(double value) const
Chris@1068 86 {
Chris@1068 87 double maxPixF = m_maxPixel;
Chris@1068 88
Chris@1137 89 if (m_params.scaleType == ColourScaleType::Phase) {
Chris@1068 90 double half = (maxPixF - 1.f) / 2.f;
Chris@1138 91 int pixel = 1 + int((value * half) / M_PI + half);
Chris@1143 92 // cerr << "phase = " << value << " pixel = " << pixel << endl;
Chris@1138 93 return pixel;
Chris@1068 94 }
Chris@1068 95
Chris@1070 96 value *= m_params.gain;
Chris@1137 97
Chris@1070 98 if (value < m_params.threshold) return 0;
Chris@1068 99
Chris@1068 100 double mapped = value;
Chris@1068 101
Chris@1137 102 if (m_params.scaleType == ColourScaleType::Log) {
Chris@1068 103 mapped = LogRange::map(value);
Chris@1137 104 } else if (m_params.scaleType == ColourScaleType::PlusMinusOne) {
Chris@1068 105 if (mapped < -1.f) mapped = -1.f;
Chris@1068 106 if (mapped > 1.f) mapped = 1.f;
Chris@1137 107 } else if (m_params.scaleType == ColourScaleType::Absolute) {
Chris@1068 108 if (mapped < 0.f) mapped = -mapped;
Chris@1068 109 }
Chris@1137 110
Chris@1137 111 mapped *= m_params.multiple;
Chris@1137 112
Chris@1068 113 if (mapped < m_mappedMin) {
Chris@1068 114 mapped = m_mappedMin;
Chris@1068 115 }
Chris@1068 116 if (mapped > m_mappedMax) {
Chris@1068 117 mapped = m_mappedMax;
Chris@1068 118 }
Chris@1068 119
Chris@1068 120 double proportion = (mapped - m_mappedMin) / (m_mappedMax - m_mappedMin);
Chris@1068 121
Chris@1068 122 int pixel = 0;
Chris@1068 123
Chris@1137 124 if (m_params.scaleType == ColourScaleType::Meter) {
Chris@1068 125 pixel = AudioLevel::multiplier_to_preview(proportion, m_maxPixel-1) + 1;
Chris@1068 126 } else {
Chris@1068 127 pixel = int(proportion * maxPixF) + 1;
Chris@1068 128 }
Chris@1068 129
Chris@1070 130 if (pixel < 0) {
Chris@1070 131 pixel = 0;
Chris@1070 132 }
Chris@1070 133 if (pixel > m_maxPixel) {
Chris@1070 134 pixel = m_maxPixel;
Chris@1070 135 }
Chris@1068 136 return pixel;
Chris@1068 137 }
Chris@1068 138
Chris@1068 139 QColor
Chris@1079 140 ColourScale::getColourForPixel(int pixel, int rotation) const
Chris@1068 141 {
Chris@1068 142 if (pixel < 0) {
Chris@1068 143 pixel = 0;
Chris@1068 144 }
Chris@1068 145 if (pixel > m_maxPixel) {
Chris@1068 146 pixel = m_maxPixel;
Chris@1068 147 }
Chris@1068 148 if (pixel == 0) {
Chris@1068 149 if (m_mapper.hasLightBackground()) {
Chris@1068 150 return Qt::white;
Chris@1068 151 } else {
Chris@1068 152 return Qt::black;
Chris@1068 153 }
Chris@1068 154 } else {
Chris@1068 155 int target = int(pixel) + rotation;
Chris@1068 156 while (target < 1) target += m_maxPixel;
Chris@1068 157 while (target > m_maxPixel) target -= m_maxPixel;
Chris@1068 158 return m_mapper.map(double(target));
Chris@1068 159 }
Chris@1068 160 }