Mercurial > hg > svgui
comparison layer/Colour3DPlotLayer.cpp @ 1107:6d720fe1c8cc spectrogram-minor-refactor
Remove almost all of the "old" paint logic from Colour3DPlotLayer
author | Chris Cannam |
---|---|
date | Thu, 14 Jul 2016 17:12:08 +0100 |
parents | ea5ae9dd10ba |
children | edbe229860ac |
comparison
equal
deleted
inserted
replaced
1106:8abdefce36a6 | 1107:6d720fe1c8cc |
---|---|
46 //#define DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 1 | 46 //#define DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 1 |
47 | 47 |
48 | 48 |
49 Colour3DPlotLayer::Colour3DPlotLayer() : | 49 Colour3DPlotLayer::Colour3DPlotLayer() : |
50 m_model(0), | 50 m_model(0), |
51 m_cache(0), | |
52 m_peaksCache(0), | |
53 m_cacheValidStart(0), | |
54 m_cacheValidEnd(0), | |
55 m_colourScale(ColourScaleType::Linear), | 51 m_colourScale(ColourScaleType::Linear), |
56 m_colourScaleSet(false), | 52 m_colourScaleSet(false), |
57 m_colourMap(0), | 53 m_colourMap(0), |
58 m_gain(1.0), | 54 m_gain(1.0), |
59 m_binScale(BinScale::Linear), | 55 m_binScale(BinScale::Linear), |
75 settings.endGroup(); | 71 settings.endGroup(); |
76 } | 72 } |
77 | 73 |
78 Colour3DPlotLayer::~Colour3DPlotLayer() | 74 Colour3DPlotLayer::~Colour3DPlotLayer() |
79 { | 75 { |
80 delete m_cache; | 76 invalidateRenderers(); |
81 delete m_peaksCache; //!!! this one is to go... | |
82 delete m_peakCache; | 77 delete m_peakCache; |
83 | |
84 cacheInvalid(); //!!! dup with above? | |
85 } | 78 } |
86 | 79 |
87 ColourScaleType | 80 ColourScaleType |
88 Colour3DPlotLayer::convertToColourScale(int value) | 81 Colour3DPlotLayer::convertToColourScale(int value) |
89 { | 82 { |
167 } | 160 } |
168 | 161 |
169 delete m_peakCache; | 162 delete m_peakCache; |
170 m_peakCache = 0; | 163 m_peakCache = 0; |
171 | 164 |
172 cacheInvalid(); | 165 invalidateRenderers(); |
173 | 166 |
174 emit modelReplaced(); | 167 emit modelReplaced(); |
175 emit sliceableModelReplaced(oldModel, model); | 168 emit sliceableModelReplaced(oldModel, model); |
176 } | 169 } |
177 | 170 |
178 void | 171 void |
179 Colour3DPlotLayer::cacheInvalid() | 172 Colour3DPlotLayer::cacheInvalid() |
180 { | 173 { |
181 //!!! to go | 174 invalidateRenderers(); |
182 | 175 } |
183 delete m_cache; | 176 |
184 delete m_peaksCache; | 177 void |
185 m_cache = 0; | 178 Colour3DPlotLayer::cacheInvalid(sv_frame_t /* startFrame */, |
186 m_peaksCache = 0; | 179 sv_frame_t /* endFrame */) |
187 m_cacheValidStart = 0; | 180 { |
188 m_cacheValidEnd = 0; | 181 //!!! should do this only if the range is visible |
189 | 182 delete m_peakCache; |
190 //!!! | 183 invalidateRenderers(); |
184 } | |
185 | |
186 void | |
187 Colour3DPlotLayer::invalidateRenderers() | |
188 { | |
191 for (ViewRendererMap::iterator i = m_renderers.begin(); | 189 for (ViewRendererMap::iterator i = m_renderers.begin(); |
192 i != m_renderers.end(); ++i) { | 190 i != m_renderers.end(); ++i) { |
193 delete i->second; | 191 delete i->second; |
194 } | 192 } |
195 m_renderers.clear(); | 193 m_renderers.clear(); |
196 } | |
197 | |
198 void | |
199 Colour3DPlotLayer::cacheInvalid(sv_frame_t startFrame, sv_frame_t endFrame) | |
200 { | |
201 //!!! to go | |
202 | |
203 if (!m_cache || !m_model) return; | |
204 | |
205 int modelResolution = m_model->getResolution(); | |
206 int start = int(startFrame / modelResolution); | |
207 int end = int(endFrame / modelResolution + 1); | |
208 if (m_cacheValidStart < end) m_cacheValidStart = end; | |
209 if (m_cacheValidEnd > start) m_cacheValidEnd = start; | |
210 if (m_cacheValidStart > m_cacheValidEnd) m_cacheValidEnd = m_cacheValidStart; | |
211 } | 194 } |
212 | 195 |
213 Dense3DModelPeakCache * | 196 Dense3DModelPeakCache * |
214 Colour3DPlotLayer::getPeakCache() const | 197 Colour3DPlotLayer::getPeakCache() const |
215 { | 198 { |
475 Colour3DPlotLayer::setColourScale(ColourScaleType scale) | 458 Colour3DPlotLayer::setColourScale(ColourScaleType scale) |
476 { | 459 { |
477 if (m_colourScale == scale) return; | 460 if (m_colourScale == scale) return; |
478 m_colourScale = scale; | 461 m_colourScale = scale; |
479 m_colourScaleSet = true; | 462 m_colourScaleSet = true; |
480 cacheInvalid(); | 463 invalidateRenderers(); |
481 emit layerParametersChanged(); | 464 emit layerParametersChanged(); |
482 } | 465 } |
483 | 466 |
484 void | 467 void |
485 Colour3DPlotLayer::setColourMap(int map) | 468 Colour3DPlotLayer::setColourMap(int map) |
486 { | 469 { |
487 if (m_colourMap == map) return; | 470 if (m_colourMap == map) return; |
488 m_colourMap = map; | 471 m_colourMap = map; |
489 cacheInvalid(); | 472 invalidateRenderers(); |
490 emit layerParametersChanged(); | 473 emit layerParametersChanged(); |
491 } | 474 } |
492 | 475 |
493 void | 476 void |
494 Colour3DPlotLayer::setGain(float gain) | 477 Colour3DPlotLayer::setGain(float gain) |
495 { | 478 { |
496 if (m_gain == gain) return; | 479 if (m_gain == gain) return; |
497 m_gain = gain; | 480 m_gain = gain; |
498 cacheInvalid(); | 481 invalidateRenderers(); |
499 emit layerParametersChanged(); | 482 emit layerParametersChanged(); |
500 } | 483 } |
501 | 484 |
502 float | 485 float |
503 Colour3DPlotLayer::getGain() const | 486 Colour3DPlotLayer::getGain() const |
508 void | 491 void |
509 Colour3DPlotLayer::setBinScale(BinScale binScale) | 492 Colour3DPlotLayer::setBinScale(BinScale binScale) |
510 { | 493 { |
511 if (m_binScale == binScale) return; | 494 if (m_binScale == binScale) return; |
512 m_binScale = binScale; | 495 m_binScale = binScale; |
513 cacheInvalid(); | 496 invalidateRenderers(); |
514 emit layerParametersChanged(); | 497 emit layerParametersChanged(); |
515 } | 498 } |
516 | 499 |
517 BinScale | 500 BinScale |
518 Colour3DPlotLayer::getBinScale() const | 501 Colour3DPlotLayer::getBinScale() const |
524 Colour3DPlotLayer::setNormalization(ColumnNormalization n) | 507 Colour3DPlotLayer::setNormalization(ColumnNormalization n) |
525 { | 508 { |
526 if (m_normalization == n) return; | 509 if (m_normalization == n) return; |
527 | 510 |
528 m_normalization = n; | 511 m_normalization = n; |
529 cacheInvalid(); | 512 invalidateRenderers(); |
530 | 513 |
531 emit layerParametersChanged(); | 514 emit layerParametersChanged(); |
532 } | 515 } |
533 | 516 |
534 ColumnNormalization | 517 ColumnNormalization |
541 Colour3DPlotLayer::setNormalizeVisibleArea(bool n) | 524 Colour3DPlotLayer::setNormalizeVisibleArea(bool n) |
542 { | 525 { |
543 if (m_normalizeVisibleArea == n) return; | 526 if (m_normalizeVisibleArea == n) return; |
544 | 527 |
545 m_normalizeVisibleArea = n; | 528 m_normalizeVisibleArea = n; |
546 cacheInvalid(); | 529 invalidateRenderers(); |
547 | 530 |
548 emit layerParametersChanged(); | 531 emit layerParametersChanged(); |
549 } | 532 } |
550 | 533 |
551 bool | 534 bool |
557 void | 540 void |
558 Colour3DPlotLayer::setInvertVertical(bool n) | 541 Colour3DPlotLayer::setInvertVertical(bool n) |
559 { | 542 { |
560 if (m_invertVertical == n) return; | 543 if (m_invertVertical == n) return; |
561 m_invertVertical = n; | 544 m_invertVertical = n; |
562 cacheInvalid(); | 545 invalidateRenderers(); |
563 emit layerParametersChanged(); | 546 emit layerParametersChanged(); |
564 } | 547 } |
565 | 548 |
566 void | 549 void |
567 Colour3DPlotLayer::setOpaque(bool n) | 550 Colour3DPlotLayer::setOpaque(bool n) |
568 { | 551 { |
569 if (m_opaque == n) return; | 552 if (m_opaque == n) return; |
570 m_opaque = n; | 553 m_opaque = n; |
554 invalidateRenderers(); | |
571 emit layerParametersChanged(); | 555 emit layerParametersChanged(); |
572 } | 556 } |
573 | 557 |
574 void | 558 void |
575 Colour3DPlotLayer::setSmooth(bool n) | 559 Colour3DPlotLayer::setSmooth(bool n) |
576 { | 560 { |
577 if (m_smooth == n) return; | 561 if (m_smooth == n) return; |
578 m_smooth = n; | 562 m_smooth = n; |
563 invalidateRenderers(); | |
579 emit layerParametersChanged(); | 564 emit layerParametersChanged(); |
580 } | 565 } |
581 | 566 |
582 bool | 567 bool |
583 Colour3DPlotLayer::getInvertVertical() const | 568 Colour3DPlotLayer::getInvertVertical() const |
625 Colour3DPlotLayer::isLayerScrollable(const LayerGeometryProvider *v) const | 610 Colour3DPlotLayer::isLayerScrollable(const LayerGeometryProvider *v) const |
626 { | 611 { |
627 if (m_normalizeVisibleArea) { | 612 if (m_normalizeVisibleArea) { |
628 return false; | 613 return false; |
629 } | 614 } |
630 if (shouldPaintDenseIn(v)) { | 615 //!!! if (shouldPaintDenseIn(v)) { |
631 return true; | 616 // return true; |
632 } | 617 // } |
633 QPoint discard; | 618 QPoint discard; |
634 return !v->shouldIlluminateLocalFeatures(this, discard); | 619 return !v->shouldIlluminateLocalFeatures(this, discard); |
635 } | 620 } |
636 | 621 |
637 bool | 622 bool |
872 int h = rect.height(), w = rect.width(); | 857 int h = rect.height(), w = rect.width(); |
873 | 858 |
874 int cw = getColourScaleWidth(paint); | 859 int cw = getColourScaleWidth(paint); |
875 | 860 |
876 int ch = h - 20; | 861 int ch = h - 20; |
877 if (ch > 20 && m_cache) { | 862 if (ch > 20) { |
878 | 863 |
879 double min = m_model->getMinimumLevel(); | 864 double min = m_model->getMinimumLevel(); |
880 double max = m_model->getMaximumLevel(); | 865 double max = m_model->getMaximumLevel(); |
881 | 866 |
882 double mmin = min; | 867 double mmin = min; |
909 if (m_colourScale == ColourScaleType::Log) { | 894 if (m_colourScale == ColourScaleType::Log) { |
910 value = LogRange::map(value); | 895 value = LogRange::map(value); |
911 } | 896 } |
912 int pixel = int(((value - mmin) * 256) / (mmax - mmin)); | 897 int pixel = int(((value - mmin) * 256) / (mmax - mmin)); |
913 if (pixel >= 0 && pixel < 256) { | 898 if (pixel >= 0 && pixel < 256) { |
914 QRgb c = m_cache->color(pixel); | 899 //!!! replace this |
915 paint.setPen(QColor(qRed(c), qGreen(c), qBlue(c))); | 900 // QRgb c = m_cache->color(pixel); |
901 // paint.setPen(QColor(qRed(c), qGreen(c), qBlue(c))); | |
916 paint.drawLine(5, 11 + y, cw - 5, 11 + y); | 902 paint.drawLine(5, 11 + y, cw - 5, 11 + y); |
917 } else { | 903 } else { |
918 cerr << "WARNING: Colour3DPlotLayer::paintVerticalScale: value " << value << ", mmin " << mmin << ", mmax " << mmax << " leads to invalid pixel " << pixel << endl; | 904 cerr << "WARNING: Colour3DPlotLayer::paintVerticalScale: value " << value << ", mmin " << mmin << ", mmax " << mmax << " leads to invalid pixel " << pixel << endl; |
919 } | 905 } |
920 } | 906 } |
1055 } | 1041 } |
1056 } | 1042 } |
1057 | 1043 |
1058 return values; | 1044 return values; |
1059 } | 1045 } |
1060 | 1046 /*!!! replace this |
1061 void | |
1062 Colour3DPlotLayer::fillCache(int firstColumn, int lastColumn) const | |
1063 { | |
1064 // This call requests a (perhaps partial) fill of the cache | |
1065 // between model columns firstColumn and lastColumn inclusive. | |
1066 // The cache itself always has size sufficient to contain the | |
1067 // whole model, but its validity may be less, depending on which | |
1068 // regions have been requested via calls to this function. Note | |
1069 // that firstColumn and lastColumn are *model* column numbers. If | |
1070 // the model starts at a frame > 0, a firstColumn of zero still | |
1071 // corresponds to the first column in the model, not the first | |
1072 // column on the resulting rendered layer. | |
1073 | |
1074 Profiler profiler("Colour3DPlotLayer::fillCache", true); | |
1075 | |
1076 int cacheWidth = m_model->getWidth(); | |
1077 int cacheHeight = m_model->getHeight(); | |
1078 | |
1079 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT | |
1080 cerr << "Colour3DPlotLayer::fillCache: range " << firstColumn << " -> " << lastColumn << " (cache size will be " << cacheWidth << " x " << cacheHeight << ")" << endl; | |
1081 #endif | |
1082 | |
1083 if (m_cache && m_cache->height() != cacheHeight) { | |
1084 // height has changed: delete everything rather than resizing | |
1085 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT | |
1086 cerr << "Colour3DPlotLayer::fillCache: Cache height has changed, recreating" << endl; | |
1087 #endif | |
1088 delete m_cache; | |
1089 delete m_peaksCache; | |
1090 m_cache = 0; | |
1091 m_peaksCache = 0; | |
1092 } | |
1093 | |
1094 if (m_cache && m_cache->width() != cacheWidth) { | |
1095 // width has changed and we have an existing cache: resize it | |
1096 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT | |
1097 cerr << "Colour3DPlotLayer::fillCache: Cache width has changed, resizing existing cache" << endl; | |
1098 #endif | |
1099 QImage *newCache = | |
1100 new QImage(m_cache->copy(0, 0, cacheWidth, cacheHeight)); | |
1101 delete m_cache; | |
1102 m_cache = newCache; | |
1103 if (m_peaksCache) { | |
1104 QImage *newPeaksCache = | |
1105 new QImage(m_peaksCache->copy | |
1106 (0, 0, cacheWidth / m_peakResolution + 1, cacheHeight)); | |
1107 delete m_peaksCache; | |
1108 m_peaksCache = newPeaksCache; | |
1109 } | |
1110 } | |
1111 | |
1112 if (!m_cache) { | |
1113 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT | |
1114 cerr << "Colour3DPlotLayer::fillCache: Have no cache, making one" << endl; | |
1115 #endif | |
1116 m_cache = new QImage(cacheWidth, cacheHeight, QImage::Format_Indexed8); | |
1117 m_cache->setColorCount(256); | |
1118 m_cache->fill(0); | |
1119 if (!m_normalizeVisibleArea) { | |
1120 m_peaksCache = new QImage | |
1121 (cacheWidth / m_peakResolution + 1, cacheHeight, | |
1122 QImage::Format_Indexed8); | |
1123 m_peaksCache->setColorCount(256); | |
1124 m_peaksCache->fill(0); | |
1125 } else if (m_peaksCache) { | |
1126 delete m_peaksCache; | |
1127 m_peaksCache = 0; | |
1128 } | |
1129 m_cacheValidStart = 0; | |
1130 m_cacheValidEnd = 0; | |
1131 } | |
1132 | |
1133 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT | |
1134 cerr << "cache size = " << m_cache->width() << "x" << m_cache->height() | |
1135 << " peaks cache size = " << m_peaksCache->width() << "x" << m_peaksCache->height() << endl; | |
1136 #endif | |
1137 | |
1138 if (m_cacheValidStart <= firstColumn && m_cacheValidEnd >= lastColumn) { | |
1139 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT | |
1140 cerr << "Cache is valid in this region already" << endl; | |
1141 #endif | |
1142 return; | |
1143 } | |
1144 | |
1145 int fillStart = firstColumn; | |
1146 int fillEnd = lastColumn; | |
1147 | |
1148 if (fillStart >= cacheWidth) fillStart = cacheWidth-1; | |
1149 if (fillStart < 0) fillStart = 0; | |
1150 if (fillEnd >= cacheWidth) fillEnd = cacheWidth-1; | |
1151 if (fillEnd < 0) fillEnd = 0; | |
1152 if (fillEnd < fillStart) fillEnd = fillStart; | |
1153 | |
1154 bool normalizeVisible = (m_normalizeVisibleArea); | |
1155 | |
1156 if (!normalizeVisible && (m_cacheValidStart < m_cacheValidEnd)) { | |
1157 | |
1158 if (m_cacheValidEnd < fillStart) { | |
1159 fillStart = m_cacheValidEnd + 1; | |
1160 } | |
1161 if (m_cacheValidStart > fillEnd) { | |
1162 fillEnd = m_cacheValidStart - 1; | |
1163 } | |
1164 | |
1165 m_cacheValidStart = std::min(fillStart, m_cacheValidStart); | |
1166 m_cacheValidEnd = std::max(fillEnd, m_cacheValidEnd); | |
1167 | |
1168 } else { | |
1169 | |
1170 // when normalising the visible area, the only valid area, | |
1171 // ever, is the currently visible one | |
1172 | |
1173 m_cacheValidStart = fillStart; | |
1174 m_cacheValidEnd = fillEnd; | |
1175 } | |
1176 | |
1177 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT | |
1178 cerr << "Cache size " << cacheWidth << "x" << cacheHeight << " will be valid from " << m_cacheValidStart << " to " << m_cacheValidEnd << " (fillStart = " << fillStart << ", fillEnd = " << fillEnd << ")" << endl; | |
1179 #endif | |
1180 | |
1181 DenseThreeDimensionalModel::Column values; | |
1182 | |
1183 double min = m_model->getMinimumLevel(); | |
1184 double max = m_model->getMaximumLevel(); | |
1185 | |
1186 if (m_colourScale == ColourScaleType::Log) { | |
1187 LogRange::mapRange(min, max); | |
1188 } else if (m_colourScale == ColourScaleType::PlusMinusOne) { | |
1189 min = -1.f; | |
1190 max = 1.f; | |
1191 } else if (m_colourScale == ColourScaleType::Absolute) { | |
1192 if (min < 0) { | |
1193 if (fabs(min) > fabs(max)) max = fabs(min); | |
1194 else max = fabs(max); | |
1195 min = 0; | |
1196 } else { | |
1197 min = fabs(min); | |
1198 max = fabs(max); | |
1199 } | |
1200 } | |
1201 | |
1202 if (max == min) max = min + 1.f; | |
1203 | |
1204 ColourMapper mapper(m_colourMap, 0.f, 255.f); | |
1205 | |
1206 for (int index = 0; index < 256; ++index) { | |
1207 QColor colour = mapper.map(index); | |
1208 m_cache->setColor | |
1209 (index, qRgb(colour.red(), colour.green(), colour.blue())); | |
1210 if (m_peaksCache) { | |
1211 m_peaksCache->setColor | |
1212 (index, qRgb(colour.red(), colour.green(), colour.blue())); | |
1213 } | |
1214 } | |
1215 | |
1216 double visibleMax = 0.f, visibleMin = 0.f; | |
1217 | |
1218 if (normalizeVisible) { | |
1219 | |
1220 for (int c = fillStart; c <= fillEnd; ++c) { | |
1221 | |
1222 values = getColumn(c); | |
1223 | |
1224 double colMax = 0.f, colMin = 0.f; | |
1225 | |
1226 for (int y = 0; y < cacheHeight; ++y) { | |
1227 if (!in_range_for(values, y)) break; | |
1228 if (y == 0 || values[y] > colMax) colMax = values[y]; | |
1229 if (y == 0 || values[y] < colMin) colMin = values[y]; | |
1230 } | |
1231 | |
1232 if (c == fillStart || colMax > visibleMax) visibleMax = colMax; | |
1233 if (c == fillStart || colMin < visibleMin) visibleMin = colMin; | |
1234 } | |
1235 | |
1236 if (m_colourScale == ColourScaleType::Log) { | |
1237 visibleMin = LogRange::map(visibleMin); | |
1238 visibleMax = LogRange::map(visibleMax); | |
1239 if (visibleMin > visibleMax) std::swap(visibleMin, visibleMax); | |
1240 } else if (m_colourScale == ColourScaleType::Absolute) { | |
1241 if (visibleMin < 0) { | |
1242 if (fabs(visibleMin) > fabs(visibleMax)) visibleMax = fabs(visibleMin); | |
1243 else visibleMax = fabs(visibleMax); | |
1244 visibleMin = 0; | |
1245 } else { | |
1246 visibleMin = fabs(visibleMin); | |
1247 visibleMax = fabs(visibleMax); | |
1248 } | |
1249 } | |
1250 } | |
1251 | |
1252 if (visibleMin == visibleMax) visibleMax = visibleMin + 1; | |
1253 | |
1254 int *peaks = 0; | |
1255 if (m_peaksCache) { | |
1256 peaks = new int[cacheHeight]; | |
1257 for (int y = 0; y < cacheHeight; ++y) { | |
1258 peaks[y] = 0; | |
1259 } | |
1260 } | |
1261 | |
1262 Profiler profiler2("Colour3DPlotLayer::fillCache: filling", true); | |
1263 | |
1264 for (int c = fillStart; c <= fillEnd; ++c) { | |
1265 | |
1266 values = getColumn(c); | |
1267 | |
1268 if (c >= m_cache->width()) { | |
1269 cerr << "ERROR: column " << c << " >= cache width " | |
1270 << m_cache->width() << endl; | |
1271 continue; | |
1272 } | |
1273 | |
1274 for (int y = 0; y < cacheHeight; ++y) { | |
1275 | |
1276 double value = min; | |
1277 if (in_range_for(values, y)) { | |
1278 value = values.at(y); | |
1279 } | |
1280 | |
1281 value = value * m_gain; | |
1282 | |
1283 if (m_colourScale == ColourScaleType::Log) { | |
1284 value = LogRange::map(value); | |
1285 } else if (m_colourScale == ColourScaleType::Absolute) { | |
1286 value = fabs(value); | |
1287 } | |
1288 | |
1289 if (normalizeVisible) { | |
1290 double norm = (value - visibleMin) / (visibleMax - visibleMin); | |
1291 value = min + (max - min) * norm; | |
1292 } | |
1293 | |
1294 int pixel = int(((value - min) * 256) / (max - min)); | |
1295 if (pixel < 0) pixel = 0; | |
1296 if (pixel > 255) pixel = 255; | |
1297 if (peaks && (pixel > peaks[y])) peaks[y] = pixel; | |
1298 | |
1299 if (m_invertVertical) { | |
1300 m_cache->setPixel(c, cacheHeight - y - 1, pixel); | |
1301 } else { | |
1302 if (y >= m_cache->height()) { | |
1303 cerr << "ERROR: row " << y << " >= cache height " << m_cache->height() << endl; | |
1304 } else { | |
1305 m_cache->setPixel(c, y, pixel); | |
1306 } | |
1307 } | |
1308 } | |
1309 | |
1310 if (peaks) { | |
1311 int notch = (c % m_peakResolution); | |
1312 if (notch == m_peakResolution-1 || c == fillEnd) { | |
1313 int pc = c / m_peakResolution; | |
1314 if (pc >= m_peaksCache->width()) { | |
1315 cerr << "ERROR: peak column " << pc | |
1316 << " (from col " << c << ") >= peaks cache width " | |
1317 << m_peaksCache->width() << endl; | |
1318 continue; | |
1319 } | |
1320 for (int y = 0; y < cacheHeight; ++y) { | |
1321 if (m_invertVertical) { | |
1322 m_peaksCache->setPixel(pc, cacheHeight - y - 1, peaks[y]); | |
1323 } else { | |
1324 if (y >= m_peaksCache->height()) { | |
1325 cerr << "ERROR: row " << y | |
1326 << " >= peaks cache height " | |
1327 << m_peaksCache->height() << endl; | |
1328 } else { | |
1329 m_peaksCache->setPixel(pc, y, peaks[y]); | |
1330 } | |
1331 } | |
1332 } | |
1333 for (int y = 0; y < cacheHeight; ++y) { | |
1334 peaks[y] = 0; | |
1335 } | |
1336 } | |
1337 } | |
1338 } | |
1339 | |
1340 delete[] peaks; | |
1341 } | |
1342 | |
1343 bool | 1047 bool |
1344 Colour3DPlotLayer::shouldPaintDenseIn(const LayerGeometryProvider *v) const | 1048 Colour3DPlotLayer::shouldPaintDenseIn(const LayerGeometryProvider *v) const |
1345 { | 1049 { |
1346 if (!m_model || !v || !(v->getViewManager())) { | 1050 if (!m_model || !v || !(v->getViewManager())) { |
1347 return false; | 1051 return false; |
1354 ((m_model->getResolution() * srRatio) / v->getZoomLevel()) < 2) { | 1058 ((m_model->getResolution() * srRatio) / v->getZoomLevel()) < 2) { |
1355 return true; | 1059 return true; |
1356 } | 1060 } |
1357 return false; | 1061 return false; |
1358 } | 1062 } |
1359 | 1063 */ |
1360 Colour3DPlotRenderer * | 1064 Colour3DPlotRenderer * |
1361 Colour3DPlotLayer::getRenderer(LayerGeometryProvider *v) const | 1065 Colour3DPlotLayer::getRenderer(LayerGeometryProvider *v) const |
1362 { | 1066 { |
1363 if (m_renderers.find(v->getId()) == m_renderers.end()) { | 1067 if (m_renderers.find(v->getId()) == m_renderers.end()) { |
1364 | 1068 |
1386 | 1090 |
1387 return m_renderers[v->getId()]; | 1091 return m_renderers[v->getId()]; |
1388 } | 1092 } |
1389 | 1093 |
1390 void | 1094 void |
1391 Colour3DPlotLayer::paintAlternative(LayerGeometryProvider *v, QPainter &paint, QRect rect) const | 1095 Colour3DPlotLayer::paintWithRenderer(LayerGeometryProvider *v, |
1096 QPainter &paint, QRect rect) const | |
1392 { | 1097 { |
1393 static int depth = 0; | 1098 static int depth = 0; |
1394 | 1099 |
1395 Colour3DPlotRenderer *renderer = getRenderer(v); | 1100 Colour3DPlotRenderer *renderer = getRenderer(v); |
1396 | 1101 |
1445 << "nothing to paint (yet)" << endl; | 1150 << "nothing to paint (yet)" << endl; |
1446 #endif | 1151 #endif |
1447 return; | 1152 return; |
1448 } | 1153 } |
1449 | 1154 |
1155 //!!!??? | |
1156 | |
1157 if (m_normalizeVisibleArea) { | |
1158 rect = v->getPaintRect(); | |
1159 } | |
1160 | |
1450 //!!! why is the setLayerDormant(false) found here in | 1161 //!!! why is the setLayerDormant(false) found here in |
1451 //!!! SpectrogramLayer not present in Colour3DPlotLayer? | 1162 //!!! SpectrogramLayer not present in Colour3DPlotLayer? |
1452 //!!! unnecessary? vestigial? forgotten? | 1163 //!!! unnecessary? vestigial? forgotten? |
1453 | 1164 |
1454 paintAlternative(v, paint, rect); | 1165 paintWithRenderer(v, paint, rect); |
1455 return; | 1166 } |
1456 | 1167 |
1457 //!!!??? | 1168 /*!!! This will be needed in some form still. |
1458 | |
1459 if (m_normalizeVisibleArea) { | |
1460 rect = v->getPaintRect(); | |
1461 } | |
1462 | 1169 |
1463 sv_frame_t modelStart = m_model->getStartFrame(); | 1170 sv_frame_t modelStart = m_model->getStartFrame(); |
1464 sv_frame_t modelEnd = m_model->getEndFrame(); | 1171 sv_frame_t modelEnd = m_model->getEndFrame(); |
1465 int modelResolution = m_model->getResolution(); | 1172 int modelResolution = m_model->getResolution(); |
1466 | 1173 |
1598 } | 1305 } |
1599 } | 1306 } |
1600 } | 1307 } |
1601 } | 1308 } |
1602 } | 1309 } |
1603 | 1310 */ |
1604 void | 1311 |
1605 Colour3DPlotLayer::paintDense(LayerGeometryProvider *v, QPainter &paint, QRect rect) const | |
1606 { | |
1607 Profiler profiler("Colour3DPlotLayer::paintDense", true); | |
1608 if (!m_cache) return; | |
1609 | |
1610 double modelStart = double(m_model->getStartFrame()); | |
1611 double modelResolution = double(m_model->getResolution()); | |
1612 | |
1613 sv_samplerate_t mmsr = v->getViewManager()->getMainModelSampleRate(); | |
1614 sv_samplerate_t msr = m_model->getSampleRate(); | |
1615 double srRatio = mmsr / msr; | |
1616 | |
1617 int x0 = rect.left(); | |
1618 int x1 = rect.right() + 1; | |
1619 | |
1620 const int w = x1 - x0; // const so it can be used as array size below | |
1621 int h = v->getPaintHeight(); // we always paint full height | |
1622 int sh = m_model->getHeight(); | |
1623 | |
1624 int symin = m_miny; | |
1625 int symax = m_maxy; | |
1626 if (symax <= symin) { | |
1627 symin = 0; | |
1628 symax = sh; | |
1629 } | |
1630 if (symin < 0) symin = 0; | |
1631 if (symax > sh) symax = sh; | |
1632 | |
1633 QImage img(w, h, QImage::Format_Indexed8); | |
1634 img.setColorTable(m_cache->colorTable()); | |
1635 | |
1636 uchar *peaks = new uchar[w]; | |
1637 memset(peaks, 0, w); | |
1638 | |
1639 int zoomLevel = v->getZoomLevel(); | |
1640 | |
1641 QImage *source = m_cache; | |
1642 | |
1643 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT | |
1644 cerr << "modelResolution " << modelResolution << ", srRatio " | |
1645 << srRatio << ", m_peakResolution " << m_peakResolution | |
1646 << ", zoomLevel " << zoomLevel << ", result " | |
1647 << ((modelResolution * srRatio * m_peakResolution) / zoomLevel) | |
1648 << endl; | |
1649 #endif | |
1650 | |
1651 if (m_peaksCache) { | |
1652 if (((modelResolution * srRatio * m_peakResolution) / zoomLevel) < 1) { | |
1653 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT | |
1654 cerr << "using peaks cache" << endl; | |
1655 #endif | |
1656 source = m_peaksCache; | |
1657 modelResolution *= m_peakResolution; | |
1658 } else { | |
1659 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT | |
1660 cerr << "not using peaks cache" << endl; | |
1661 #endif | |
1662 } | |
1663 } else { | |
1664 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT | |
1665 cerr << "have no peaks cache" << endl; | |
1666 #endif | |
1667 } | |
1668 | |
1669 int sw = source->width(); | |
1670 | |
1671 sv_frame_t xf = -1; | |
1672 sv_frame_t nxf = v->getFrameForX(x0); | |
1673 | |
1674 double epsilon = 0.000001; | |
1675 | |
1676 vector<double> sxa(w*2); | |
1677 | |
1678 for (int x = 0; x < w; ++x) { | |
1679 | |
1680 xf = nxf; | |
1681 nxf = xf + zoomLevel; | |
1682 | |
1683 double sx0 = (double(xf) / srRatio - modelStart) / modelResolution; | |
1684 double sx1 = (double(nxf) / srRatio - modelStart) / modelResolution; | |
1685 | |
1686 sxa[x*2] = sx0; | |
1687 sxa[x*2 + 1] = sx1; | |
1688 } | |
1689 | |
1690 double logmin = symin+1, logmax = symax+1; | |
1691 LogRange::mapRange(logmin, logmax); | |
1692 | |
1693 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT | |
1694 cerr << "m_smooth = " << m_smooth << ", w = " << w << ", h = " << h << endl; | |
1695 #endif | |
1696 | |
1697 if (m_smooth) { | |
1698 | |
1699 for (int y = 0; y < h; ++y) { | |
1700 | |
1701 double sy = getBinForY(v, y) - 0.5; | |
1702 int syi = int(sy + epsilon); | |
1703 if (syi < 0 || syi >= source->height()) continue; | |
1704 | |
1705 uchar *targetLine = img.scanLine(y); | |
1706 uchar *sourceLine = source->scanLine(syi); | |
1707 uchar *nextSource; | |
1708 if (syi + 1 < source->height()) { | |
1709 nextSource = source->scanLine(syi + 1); | |
1710 } else { | |
1711 nextSource = sourceLine; | |
1712 } | |
1713 | |
1714 for (int x = 0; x < w; ++x) { | |
1715 | |
1716 targetLine[x] = 0; | |
1717 | |
1718 double sx0 = sxa[x*2]; | |
1719 if (sx0 < 0) continue; | |
1720 int sx0i = int(sx0 + epsilon); | |
1721 if (sx0i >= sw) break; | |
1722 | |
1723 double a = sourceLine[sx0i]; | |
1724 double b = a; | |
1725 double value; | |
1726 | |
1727 double sx1 = sxa[x*2+1]; | |
1728 if (sx1 > sx0 + 1.f) { | |
1729 int sx1i = int(sx1); | |
1730 bool have = false; | |
1731 for (int sx = sx0i; sx <= sx1i; ++sx) { | |
1732 if (sx < 0 || sx >= sw) continue; | |
1733 if (!have) { | |
1734 a = sourceLine[sx]; | |
1735 b = nextSource[sx]; | |
1736 have = true; | |
1737 } else { | |
1738 a = std::max(a, double(sourceLine[sx])); | |
1739 b = std::max(b, double(nextSource[sx])); | |
1740 } | |
1741 } | |
1742 double yprop = sy - syi; | |
1743 value = (a * (1.f - yprop) + b * yprop); | |
1744 } else { | |
1745 a = sourceLine[sx0i]; | |
1746 b = nextSource[sx0i]; | |
1747 double yprop = sy - syi; | |
1748 value = (a * (1.f - yprop) + b * yprop); | |
1749 int oi = sx0i + 1; | |
1750 double xprop = sx0 - sx0i; | |
1751 xprop -= 0.5; | |
1752 if (xprop < 0) { | |
1753 oi = sx0i - 1; | |
1754 xprop = -xprop; | |
1755 } | |
1756 if (oi < 0 || oi >= sw) oi = sx0i; | |
1757 a = sourceLine[oi]; | |
1758 b = nextSource[oi]; | |
1759 value = (value * (1.f - xprop) + | |
1760 (a * (1.f - yprop) + b * yprop) * xprop); | |
1761 } | |
1762 | |
1763 int vi = int(lrint(value)); | |
1764 if (vi > 255) vi = 255; | |
1765 if (vi < 0) vi = 0; | |
1766 targetLine[x] = uchar(vi); | |
1767 } | |
1768 } | |
1769 } else { | |
1770 | |
1771 double sy0 = getBinForY(v, 0); | |
1772 | |
1773 int psy0i = -1, psy1i = -1; | |
1774 | |
1775 for (int y = 0; y < h; ++y) { | |
1776 | |
1777 double sy1 = sy0; | |
1778 sy0 = getBinForY(v, double(y + 1)); | |
1779 | |
1780 int sy0i = int(sy0 + epsilon); | |
1781 int sy1i = int(sy1); | |
1782 | |
1783 uchar *targetLine = img.scanLine(y); | |
1784 | |
1785 if (sy0i == psy0i && sy1i == psy1i) { | |
1786 // same source scan line as just computed | |
1787 goto copy; | |
1788 } | |
1789 | |
1790 psy0i = sy0i; | |
1791 psy1i = sy1i; | |
1792 | |
1793 for (int x = 0; x < w; ++x) { | |
1794 peaks[x] = 0; | |
1795 } | |
1796 | |
1797 for (int sy = sy0i; sy <= sy1i; ++sy) { | |
1798 | |
1799 if (sy < 0 || sy >= source->height()) continue; | |
1800 | |
1801 uchar *sourceLine = source->scanLine(sy); | |
1802 | |
1803 for (int x = 0; x < w; ++x) { | |
1804 | |
1805 double sx1 = sxa[x*2 + 1]; | |
1806 if (sx1 < 0) continue; | |
1807 int sx1i = int(sx1); | |
1808 | |
1809 double sx0 = sxa[x*2]; | |
1810 if (sx0 < 0) continue; | |
1811 int sx0i = int(sx0 + epsilon); | |
1812 if (sx0i >= sw) break; | |
1813 | |
1814 uchar peak = 0; | |
1815 for (int sx = sx0i; sx <= sx1i; ++sx) { | |
1816 if (sx < 0 || sx >= sw) continue; | |
1817 if (sourceLine[sx] > peak) peak = sourceLine[sx]; | |
1818 } | |
1819 peaks[x] = peak; | |
1820 } | |
1821 } | |
1822 | |
1823 copy: | |
1824 for (int x = 0; x < w; ++x) { | |
1825 targetLine[x] = peaks[x]; | |
1826 } | |
1827 } | |
1828 } | |
1829 | |
1830 delete[] peaks; | |
1831 | |
1832 paint.drawImage(x0, 0, img); | |
1833 } | |
1834 | 1312 |
1835 bool | 1313 bool |
1836 Colour3DPlotLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame, | 1314 Colour3DPlotLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame, |
1837 int &resolution, | 1315 int &resolution, |
1838 SnapType snap) const | 1316 SnapType snap) const |