19 #include "base/Profiler.h" 20 #include "base/LogRange.h" 21 #include "base/RangeMapper.h" 27 #include <QTextStream> 46 m_colourScale(LinearScale),
47 m_colourScaleSet(false),
50 m_binScale(LinearBinScale),
51 m_normalizeColumns(false),
52 m_normalizeVisibleArea(false),
53 m_normalizeHybrid(false),
54 m_invertVertical(false),
57 m_peakResolution(256),
74 const DenseThreeDimensionalModel *oldModel =
m_model;
85 if (model->getResolution() > 512) {
87 }
else if (model->getResolution() > 128) {
89 }
else if (model->getResolution() > 2) {
114 int modelResolution =
m_model->getResolution();
115 int start = startFrame / modelResolution;
116 int end = endFrame / modelResolution + 1;
127 if (
m_model->shouldUseLogValueScale()) {
142 if (
m_model->shouldUseLogValueScale()) {
156 list.push_back(
"Colour");
157 list.push_back(
"Colour Scale");
158 list.push_back(
"Normalize Columns");
159 list.push_back(
"Normalize Visible Area");
160 list.push_back(
"Gain");
161 list.push_back(
"Bin Scale");
162 list.push_back(
"Invert Vertical Scale");
163 list.push_back(
"Opaque");
164 list.push_back(
"Smooth");
171 if (name ==
"Colour")
return tr(
"Colour");
172 if (name ==
"Colour Scale")
return tr(
"Scale");
173 if (name ==
"Normalize Columns")
return tr(
"Normalize Columns");
174 if (name ==
"Normalize Visible Area")
return tr(
"Normalize Visible Area");
175 if (name ==
"Invert Vertical Scale")
return tr(
"Invert Vertical Scale");
176 if (name ==
"Gain")
return tr(
"Gain");
177 if (name ==
"Opaque")
return tr(
"Always Opaque");
178 if (name ==
"Smooth")
return tr(
"Smooth");
179 if (name ==
"Bin Scale")
return tr(
"Bin Scale");
186 if (name ==
"Normalize Columns")
return "normalise-columns";
187 if (name ==
"Normalize Visible Area")
return "normalise";
188 if (name ==
"Invert Vertical Scale")
return "invert-vertical";
189 if (name ==
"Opaque")
return "opaque";
190 if (name ==
"Smooth")
return "smooth";
197 if (name ==
"Gain")
return RangeProperty;
198 if (name ==
"Normalize Columns")
return ToggleProperty;
199 if (name ==
"Normalize Visible Area")
return ToggleProperty;
200 if (name ==
"Invert Vertical Scale")
return ToggleProperty;
201 if (name ==
"Opaque")
return ToggleProperty;
202 if (name ==
"Smooth")
return ToggleProperty;
203 return ValueProperty;
209 if (name ==
"Normalize Columns" ||
210 name ==
"Normalize Visible Area" ||
211 name ==
"Colour Scale" ||
212 name ==
"Gain")
return tr(
"Scale");
213 if (name ==
"Bin Scale" ||
214 name ==
"Invert Vertical Scale")
return tr(
"Bins");
215 if (name ==
"Opaque" ||
217 name ==
"Colour")
return tr(
"Colour");
223 int *min,
int *max,
int *deflt)
const 227 int garbage0, garbage1, garbage2;
228 if (!min) min = &garbage0;
229 if (!max) max = &garbage1;
230 if (!deflt) deflt = &garbage2;
232 if (name ==
"Gain") {
237 *deflt = lrintf(log10(1.f) * 20.0);;
238 if (*deflt < *min) *deflt = *min;
239 if (*deflt > *max) *deflt = *max;
241 val = lrintf(log10(
m_gain) * 20.0);
242 if (val < *min) val = *min;
243 if (val > *max) val = *max;
245 }
else if (name ==
"Colour Scale") {
253 }
else if (name ==
"Colour") {
261 }
else if (name ==
"Normalize Columns") {
266 }
else if (name ==
"Normalize Visible Area") {
271 }
else if (name ==
"Invert Vertical Scale") {
276 }
else if (name ==
"Bin Scale") {
283 }
else if (name ==
"Opaque") {
288 }
else if (name ==
"Smooth") {
294 val = Layer::getPropertyRangeAndValue(name, min, max, deflt);
304 if (name ==
"Colour") {
307 if (name ==
"Colour Scale") {
310 case 0:
return tr(
"Linear");
311 case 1:
return tr(
"Log");
312 case 2:
return tr(
"+/-1");
313 case 3:
return tr(
"Absolute");
316 if (name ==
"Bin Scale") {
319 case 0:
return tr(
"Linear");
320 case 1:
return tr(
"Log");
323 return tr(
"<unknown>");
329 if (name ==
"Gain") {
330 return new LinearRangeMapper(-50, 50, -25, 25, tr(
"dB"));
338 if (name ==
"Gain") {
339 setGain(pow(10,
float(value)/20.0));
340 }
else if (name ==
"Colour Scale") {
348 }
else if (name ==
"Colour") {
350 }
else if (name ==
"Normalize Columns") {
352 }
else if (name ==
"Normalize Visible Area") {
354 }
else if (name ==
"Invert Vertical Scale") {
356 }
else if (name ==
"Opaque") {
358 }
else if (name ==
"Smooth") {
360 }
else if (name ==
"Bin Scale") {
391 if (
m_gain == gain)
return;
511 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 512 cerr <<
"Colour3DPlotLayer::setLayerDormant(" << dormant <<
")" 545 bool &logarithmic, QString &unit)
const 569 if (min < 0) min = 0;
589 float &, QString &)
const 611 return m_model->getHeight() - lrintf(max - min);
621 int dist =
m_model->getHeight() - step;
622 if (dist < 1) dist = 1;
624 m_miny = lrintf(centre -
float(dist)/2);
639 return new LinearRangeMapper(0,
m_model->getHeight(),
648 float mn = 0, mx =
m_model->getHeight();
650 float h = v->height();
652 y = h - (((bin - mn) * h) / (mx - mn));
654 float logmin = mn + 1, logmax = mx + 1;
655 LogRange::mapRange(logmin, logmax);
656 y = h - (((LogRange::map(bin + 1) - logmin) * h) / (logmax - logmin));
666 float mn = 0, mx =
m_model->getHeight();
668 float h = v->height();
670 bin = mn + ((h - y) * (mx - mn)) / h;
672 float logmin = mn + 1, logmax = mx + 1;
673 LogRange::mapRange(logmin, logmax);
674 bin = LogRange::unmap(logmin + ((h - y) * (logmax - logmin)) / h) - 1;
687 int modelStart =
m_model->getStartFrame();
688 int modelResolution =
m_model->getResolution();
692 float(
m_model->getSampleRate());
694 int sx0 = int((v->
getFrameForX(x) / srRatio - modelStart) /
697 int f0 = sx0 * modelResolution;
698 int f1 = f0 + modelResolution;
704 if (symax <= symin) {
708 if (symin < 0) symin = 0;
709 if (symax > sh) symax = sh;
716 if (sy < 0 || sy >=
m_model->getHeight()) {
722 float value =
m_model->getValueAt(sx0, sy);
726 QString binName =
m_model->getBinName(sy);
727 if (binName ==
"") binName = QString(
"[%1]").arg(sy + 1);
728 else binName = QString(
"%1 [%2]").arg(binName).arg(sy + 1);
730 QString text = tr(
"Time:\t%1 - %2\nBin:\t%3\nValue:\t%4")
731 .arg(RealTime::frame2RealTime(f0,
m_model->getSampleRate())
732 .toText(
true).c_str())
733 .arg(RealTime::frame2RealTime(f1,
m_model->getSampleRate())
734 .toText(
true).c_str())
753 QString sampleText = QString(
"[%1]").arg(
m_model->getHeight());
754 int tw =
paint.fontMetrics().width(sampleText);
755 bool another =
false;
757 for (
int i = 0; i <
m_model->getHeight(); ++i) {
758 if (
m_model->getBinName(i).length() > sampleText.length()) {
759 sampleText =
m_model->getBinName(i);
764 tw = std::max(tw,
paint.fontMetrics().width(sampleText));
775 int h = rect.height(), w = rect.width();
782 float min =
m_model->getMinimumLevel();
783 float max =
m_model->getMaximumLevel();
789 LogRange::mapRange(mmin, mmax);
795 if (fabsf(mmin) > fabsf(mmax)) mmax = fabsf(mmin);
796 else mmax = fabsf(mmax);
804 if (max == min) max = min + 1.0;
805 if (mmax == mmin) mmax = mmin + 1.0;
808 paint.drawRect(4, 10, cw - 8, ch+1);
810 for (
int y = 0; y < ch; ++y) {
811 float value = ((max - min) * (ch - y - 1)) / ch + min;
813 value = LogRange::map(value);
815 int pixel = int(((value - mmin) * 256) / (mmax - mmin));
816 if (pixel >= 0 && pixel < 256) {
817 QRgb c =
m_cache->color(pixel);
818 paint.setPen(QColor(qRed(c), qGreen(c), qBlue(c)));
819 paint.drawLine(5, 11 + y, cw - 5, 11 + y);
821 cerr <<
"WARNING: Colour3DPlotLayer::paintVerticalScale: value " << value <<
", mmin " << mmin <<
", mmax " << mmax <<
" leads to invalid pixel " << pixel << endl;
825 QString minstr = QString(
"%1").arg(min);
826 QString maxstr = QString(
"%1").arg(max);
830 QFont font =
paint.font();
831 font.setPixelSize(10);
834 int msw =
paint.fontMetrics().width(maxstr);
837 m.translate(cw - 6, ch + 10);
840 paint.setWorldMatrix(m);
844 m.translate(ch - msw - 2, 0);
845 paint.setWorldMatrix(m);
858 if (symax <= symin) {
862 if (symin < 0) symin = 0;
863 if (symax > sh) symax = sh;
869 for (
int i = symin; i <= symax; ++i) {
877 if (
paint.fontMetrics().height() >= h) {
879 QFont tf =
paint.font();
880 tf.setPixelSize(h-2);
891 paint.drawLine(cw, y0, w, y0);
899 QString text =
m_model->getBinName(idx);
900 if (text ==
"") text = QString(
"[%1]").arg(idx + 1);
902 int ty = y0 + (h/2) - (
paint.fontMetrics().height()/2) +
903 paint.fontMetrics().ascent() + 1;
905 paint.drawText(cw + 5, ty, text);
912 DenseThreeDimensionalModel::Column
915 Profiler profiler(
"Colour3DPlotLayer::getColumn");
917 DenseThreeDimensionalModel::Column values =
m_model->getColumn(col);
918 while (values.size() <
m_model->getHeight()) values.push_back(0.f);
921 float colMax = 0.f, colMin = 0.f;
922 float min = 0.f, max = 0.f;
924 min =
m_model->getMinimumLevel();
925 max =
m_model->getMaximumLevel();
927 for (
int y = 0; y < values.size(); ++y) {
928 if (y == 0 || values.at(y) > colMax) colMax = values.at(y);
929 if (y == 0 || values.at(y) < colMin) colMin = values.at(y);
931 if (colMin == colMax) colMax = colMin + 1;
933 for (
int y = 0; y < values.size(); ++y) {
935 float value = values.at(y);
936 float norm = (value - colMin) / (colMax - colMin);
937 float newvalue = min + (max - min) * norm;
939 if (value != newvalue) values[y] = newvalue;
943 float logmax = log10(colMax);
944 for (
int y = 0; y < values.size(); ++y) {
955 Profiler profiler(
"Colour3DPlotLayer::fillCache",
true);
957 int modelStart =
m_model->getStartFrame();
958 int modelEnd =
m_model->getEndFrame();
959 int modelResolution =
m_model->getResolution();
961 int modelStartBin = modelStart / modelResolution;
962 int modelEndBin = modelEnd / modelResolution;
964 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 965 cerr <<
"Colour3DPlotLayer::fillCache: range " << firstBin <<
" -> " << lastBin <<
" of model range " << modelStartBin <<
" -> " << modelEndBin <<
" (model resolution " << modelResolution <<
")" << endl;
968 int cacheWidth = modelEndBin - modelStartBin + 1;
969 if (lastBin > modelEndBin) cacheWidth = lastBin - modelStartBin + 1;
970 int cacheHeight =
m_model->getHeight();
974 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 975 cerr <<
"Colour3DPlotLayer::fillCache: Cache height has changed, recreating" << endl;
985 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 986 cerr <<
"Colour3DPlotLayer::fillCache: Cache width has changed, resizing existing cache" << endl;
989 new QImage(
m_cache->copy(0, 0, cacheWidth, cacheHeight));
993 QImage *newPeaksCache =
1002 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 1003 cerr <<
"Colour3DPlotLayer::fillCache: Have no cache, making one" << endl;
1006 (cacheWidth, cacheHeight, QImage::Format_Indexed8);
1012 QImage::Format_Indexed8);
1023 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 1024 cerr <<
"cache size = " <<
m_cache->width() <<
"x" <<
m_cache->height()
1028 if (m_cacheValidStart <= firstBin && m_cacheValidEnd >= lastBin) {
1029 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 1030 cerr <<
"Cache is valid in this region already" << endl;
1035 int fillStart = firstBin;
1036 int fillEnd = lastBin;
1038 if (fillStart < modelStartBin) fillStart = modelStartBin;
1039 if (fillStart > modelEndBin) fillStart = modelEndBin;
1040 if (fillEnd < modelStartBin) fillEnd = modelStartBin;
1041 if (fillEnd > modelEndBin) fillEnd = modelEndBin;
1066 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 1067 cerr <<
"Cache size " << cacheWidth <<
"x" << cacheHeight <<
" will be valid from " <<
m_cacheValidStart <<
" to " <<
m_cacheValidEnd <<
" (fillStart = " << fillStart <<
", fillEnd = " << fillEnd <<
")" << endl;
1070 DenseThreeDimensionalModel::Column values;
1072 float min =
m_model->getMinimumLevel();
1073 float max =
m_model->getMaximumLevel();
1076 LogRange::mapRange(min, max);
1082 if (fabsf(min) > fabsf(max)) max = fabsf(min);
1083 else max = fabsf(max);
1091 if (max == min) max = min + 1.0;
1095 for (
int index = 0; index < 256; ++index) {
1096 QColor colour = mapper.
map(index);
1098 (index, qRgb(colour.red(), colour.green(), colour.blue()));
1101 (index, qRgb(colour.red(), colour.green(), colour.blue()));
1105 float visibleMax = 0.f, visibleMin = 0.f;
1107 if (normalizeVisible) {
1109 for (
int c = fillStart; c <= fillEnd; ++c) {
1113 float colMax = 0.f, colMin = 0.f;
1115 for (
int y = 0; y < cacheHeight; ++y) {
1116 if (y >= values.size())
break;
1117 if (y == 0 || values[y] > colMax) colMax = values[y];
1118 if (y == 0 || values[y] < colMin) colMin = values[y];
1121 if (c == fillStart || colMax > visibleMax) visibleMax = colMax;
1122 if (c == fillStart || colMin < visibleMin) visibleMin = colMin;
1126 visibleMin = LogRange::map(visibleMin);
1127 visibleMax = LogRange::map(visibleMax);
1128 if (visibleMin > visibleMax) std::swap(visibleMin, visibleMax);
1130 if (visibleMin < 0) {
1131 if (fabsf(visibleMin) > fabsf(visibleMax)) visibleMax = fabsf(visibleMin);
1132 else visibleMax = fabsf(visibleMax);
1135 visibleMin = fabsf(visibleMin);
1136 visibleMax = fabsf(visibleMax);
1141 if (visibleMin == visibleMax) visibleMax = visibleMin + 1;
1145 peaks =
new int[cacheHeight];
1146 for (
int y = 0; y < cacheHeight; ++y) {
1151 Profiler profiler2(
"Colour3DPlotLayer::fillCache: filling",
true);
1153 for (
int c = fillStart; c <= fillEnd; ++c) {
1158 cerr <<
"ERROR: column " << c <<
" >= cache width " 1163 for (
int y = 0; y < cacheHeight; ++y) {
1166 if (y < values.size()) {
1167 value = values.at(y);
1173 value = LogRange::map(value);
1175 value = fabsf(value);
1178 if (normalizeVisible) {
1179 float norm = (value - visibleMin) / (visibleMax - visibleMin);
1180 value = min + (max - min) * norm;
1183 int pixel = int(((value - min) * 256) / (max - min));
1184 if (pixel < 0) pixel = 0;
1185 if (pixel > 255) pixel = 255;
1186 if (peaks && (pixel > peaks[y])) peaks[y] = pixel;
1189 m_cache->setPixel(c, cacheHeight - y - 1, pixel);
1192 cerr <<
"ERROR: row " << y <<
" >= cache height " <<
m_cache->height() << endl;
1194 m_cache->setPixel(c, y, pixel);
1204 cerr <<
"ERROR: peak column " << pc
1205 <<
" (from col " << c <<
") >= peaks cache width " 1209 for (
int y = 0; y < cacheHeight; ++y) {
1211 m_peaksCache->setPixel(pc, cacheHeight - y - 1, peaks[y]);
1214 cerr <<
"ERROR: row " << y
1215 <<
" >= peaks cache height " 1222 for (
int y = 0; y < cacheHeight; ++y) {
1240 float(
m_model->getSampleRate());
1243 m_model->getHeight() >= v->height() ||
1258 Profiler profiler(
"Colour3DPlotLayer::paint");
1259 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 1260 cerr <<
"Colour3DPlotLayer::paint(): m_model is " <<
m_model <<
", zoom level is " << v->
getZoomLevel() <<
", rect is (" << rect.x() <<
"," << rect.y() <<
") " << rect.width() <<
"x" << rect.height() << endl;
1265 if (completion > 0) {
1266 paint.fillRect(0, 10, v->width() * completion / 100,
1267 10, QColor(120, 120, 120));
1274 int modelStart =
m_model->getStartFrame();
1275 int modelEnd =
m_model->getEndFrame();
1276 int modelResolution =
m_model->getResolution();
1287 int x0 = rect.left();
1288 int x1 = rect.right() + 1;
1290 int h = v->height();
1294 float(
m_model->getSampleRate());
1296 int sx0 = int((v->
getFrameForX(x0) / srRatio - modelStart)
1298 int sx1 = int((v->
getFrameForX(x1) / srRatio - modelStart)
1300 int sh =
m_model->getHeight();
1304 if (symax <= symin) {
1308 if (symin < 0) symin = 0;
1309 if (symax > sh) symax = sh;
1315 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 1316 cerr <<
"Colour3DPlotLayer::paint: height = "<<
m_model->getHeight() <<
", modelStart = " << modelStart <<
", resolution = " << modelResolution <<
", model rate = " <<
m_model->getSampleRate() <<
" (zoom level = " << v->
getZoomLevel() <<
", srRatio = " << srRatio <<
")" << endl;
1320 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 1321 cerr <<
"calling paintDense" << endl;
1327 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 1328 cerr <<
"Colour3DPlotLayer::paint: w " << x1-x0 <<
", h " << h <<
", sx0 " << sx0 <<
", sx1 " << sx1 <<
", sw " << sx1-sx0 <<
", sh " << sh << endl;
1329 cerr <<
"Colour3DPlotLayer: sample rate is " <<
m_model->getSampleRate() <<
", resolution " <<
m_model->getResolution() << endl;
1332 QPoint illuminatePos;
1336 for (
int sx = sx0; sx <= sx1; ++sx) {
1338 int fx = sx * modelResolution;
1340 if (fx + modelResolution <= modelStart || fx > modelEnd)
continue;
1342 int rx0 = v->
getXForFrame(
int((fx + modelStart) * srRatio));
1343 int rx1 = v->
getXForFrame(
int((fx + modelStart + modelResolution + 1) * srRatio));
1348 bool showLabel = (rw > 10 &&
1349 paint.fontMetrics().width(
"0.000000") < rw - 3 &&
1350 paint.fontMetrics().height() < (h / sh));
1352 for (
int sy = symin; sy < symax; ++sy) {
1356 QRect r(rx0, ry1, rw, ry0 - ry1);
1358 QRgb pixel = qRgb(255, 255, 255);
1359 if (sx >= 0 && sx < m_cache->width() &&
1360 sy >= 0 && sy < m_cache->height()) {
1361 pixel =
m_cache->pixel(sx, sy);
1365 paint.setPen(pixel);
1366 paint.setBrush(Qt::NoBrush);
1367 paint.drawLine(r.x(), r.y(), r.x(), r.y() + r.height() - 1);
1371 QColor pen(255, 255, 255, 80);
1372 QColor brush(pixel);
1374 if (rw > 3 && r.height() > 3) {
1375 brush.setAlpha(160);
1378 paint.setPen(Qt::NoPen);
1379 paint.setBrush(brush);
1382 if (r.contains(illuminatePos)) {
1387 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 1395 if (sx >= 0 && sx < m_cache->width() &&
1396 sy >= 0 && sy < m_cache->height()) {
1397 float value =
m_model->getValueAt(sx, sy);
1398 sprintf(labelbuf,
"%06f", value);
1399 QString text(labelbuf);
1401 paint.drawText(rx0 + 2,
1402 ry0 - h / sh - 1 + 2 +
paint.fontMetrics().ascent(),
1413 Profiler profiler(
"Colour3DPlotLayer::paintDense",
true);
1416 float modelStart =
m_model->getStartFrame();
1417 float modelResolution =
m_model->getResolution();
1420 int msr =
m_model->getSampleRate();
1421 float srRatio = float(mmsr) / float(msr);
1423 int x0 = rect.left();
1424 int x1 = rect.right() + 1;
1426 const int w = x1 - x0;
1427 int h = v->height();
1428 int sh =
m_model->getHeight();
1432 if (symax <= symin) {
1436 if (symin < 0) symin = 0;
1437 if (symax > sh) symax = sh;
1439 QImage img(w, h, QImage::Format_Indexed8);
1440 img.setColorTable(
m_cache->colorTable());
1442 uchar *peaks =
new uchar[w];
1443 memset(peaks, 0, w);
1449 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 1450 cerr <<
"modelResolution " << modelResolution <<
", srRatio " 1452 <<
", zoomLevel " << zoomLevel <<
", result " 1459 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 1460 cerr <<
"using peaks cache" << endl;
1465 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 1466 cerr <<
"not using peaks cache" << endl;
1470 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 1471 cerr <<
"have no peaks cache" << endl;
1475 int sw = source->width();
1480 float epsilon = 0.000001;
1485 float *sxa = (
float *)alloca(w * 2 *
sizeof(
float));
1487 for (
int x = 0; x < w; ++x) {
1490 nxf = xf + zoomLevel;
1492 float sx0 = (float(xf) / srRatio - modelStart) / modelResolution;
1493 float sx1 = (float(nxf) / srRatio - modelStart) / modelResolution;
1499 float logmin = symin+1, logmax = symax+1;
1500 LogRange::mapRange(logmin, logmax);
1502 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 1503 cerr <<
"m_smooth = " <<
m_smooth <<
", w = " << w <<
", h = " << h << endl;
1508 for (
int y = 0; y < h; ++y) {
1511 int syi = int(sy + epsilon);
1512 if (syi < 0 || syi >= source->height())
continue;
1514 uchar *targetLine = img.scanLine(y);
1515 uchar *sourceLine = source->scanLine(syi);
1517 if (syi + 1 < source->height()) {
1518 nextSource = source->scanLine(syi + 1);
1520 nextSource = sourceLine;
1523 for (
int x = 0; x < w; ++x) {
1527 float sx0 = sxa[x*2];
1528 if (sx0 < 0)
continue;
1529 int sx0i = int(sx0 + epsilon);
1530 if (sx0i >= sw)
break;
1532 float a = float(sourceLine[sx0i]);
1536 float sx1 = sxa[x*2+1];
1537 if (sx1 > sx0 + 1.f) {
1538 int sx1i = int(sx1);
1540 for (
int sx = sx0i; sx <= sx1i; ++sx) {
1541 if (sx < 0 || sx >= sw)
continue;
1543 a = float(sourceLine[sx]);
1544 b = float(nextSource[sx]);
1547 a = std::max(a,
float(sourceLine[sx]));
1548 b = std::max(b,
float(nextSource[sx]));
1551 float yprop = sy - syi;
1552 value = (a * (1.f - yprop) + b * yprop);
1554 a = float(sourceLine[sx0i]);
1555 b = float(nextSource[sx0i]);
1556 float yprop = sy - syi;
1557 value = (a * (1.f - yprop) + b * yprop);
1559 float xprop = sx0 - sx0i;
1565 if (oi < 0 || oi >= sw) oi = sx0i;
1566 a = float(sourceLine[oi]);
1567 b = float(nextSource[oi]);
1568 value = (value * (1.f - xprop) +
1569 (a * (1.f - yprop) + b * yprop) * xprop);
1572 int vi = lrintf(value);
1573 if (vi > 255) vi = 255;
1575 targetLine[x] = uchar(vi);
1582 int psy0i = -1, psy1i = -1;
1584 for (
int y = 0; y < h; ++y) {
1589 int sy0i = int(sy0 + epsilon);
1590 int sy1i = int(sy1);
1592 uchar *targetLine = img.scanLine(y);
1594 if (sy0i == psy0i && sy1i == psy1i) {
1602 for (
int x = 0; x < w; ++x) {
1606 for (
int sy = sy0i; sy <= sy1i; ++sy) {
1608 if (sy < 0 || sy >= source->height())
continue;
1610 uchar *sourceLine = source->scanLine(sy);
1612 for (
int x = 0; x < w; ++x) {
1614 float sx1 = sxa[x*2 + 1];
1615 if (sx1 < 0)
continue;
1616 int sx1i = int(sx1);
1618 float sx0 = sxa[x*2];
1619 if (sx0 < 0)
continue;
1620 int sx0i = int(sx0 + epsilon);
1621 if (sx0i >= sw)
break;
1624 for (
int sx = sx0i; sx <= sx1i; ++sx) {
1625 if (sx < 0 || sx >= sw)
continue;
1626 if (sourceLine[sx] > peak) peak = sourceLine[sx];
1633 for (
int x = 0; x < w; ++x) {
1634 targetLine[x] = peaks[x];
1641 paint.drawImage(x0, 0, img);
1653 resolution =
m_model->getResolution();
1654 int left = (frame / resolution) * resolution;
1655 int right = left + resolution;
1658 case SnapLeft: frame = left;
break;
1662 if (frame - left > right - frame) frame = right;
1672 QString indent, QString extraAttributes)
const 1674 QString s = QString(
"scale=\"%1\" " 1675 "colourScheme=\"%2\" " 1676 "normalizeColumns=\"%3\" " 1677 "normalizeVisibleArea=\"%4\" " 1680 "invertVertical=\"%7\" " 1690 .arg(QString(
"binScale=\"%1\" smooth=\"%2\" gain=\"%3\" ")
1695 Layer::toXml(stream, indent, extraAttributes +
" " + s);
1701 bool ok =
false, alsoOk =
false;
1706 int colourMap = attributes.value(
"colourScheme").toInt(&ok);
1712 bool normalizeColumns =
1713 (attributes.value(
"normalizeColumns").trimmed() ==
"true");
1716 bool normalizeVisibleArea =
1717 (attributes.value(
"normalizeVisibleArea").trimmed() ==
"true");
1720 bool invertVertical =
1721 (attributes.value(
"invertVertical").trimmed() ==
"true");
1725 (attributes.value(
"opaque").trimmed() ==
"true");
1729 (attributes.value(
"smooth").trimmed() ==
"true");
1732 float gain = attributes.value(
"gain").toFloat(&ok);
1735 float min = attributes.value(
"minY").toFloat(&ok);
1736 float max = attributes.value(
"maxY").toFloat(&alsoOk);
int getFrameForX(int x) const
Return the closest frame to the given pixel x-coordinate.
virtual int getVerticalZoomSteps(int &defaultStep) const
Get the number of vertical zoom steps available for this layer.
virtual PropertyList getProperties() const
bool getNormalizeHybrid() const
bool shouldPaintDenseIn(const View *) const
True if we have the opaque or smooth flag set, or if the cells are so small you can't see their borde...
virtual PropertyType getPropertyType(const PropertyName &) const
virtual bool snapToFeatureFrame(View *, int &, int &resolution, SnapType) const
Adjust the given frame to snap to the nearest feature, if possible.
void connectSignals(const Model *)
virtual bool getYScaleValue(const View *, int, float &, QString &) const
Return the value and unit at the given y coordinate in the given view.
int getMainModelSampleRate() const
The sample rate of the current main model.
void fillCache(int firstBin, int lastBin) const
virtual bool setDisplayExtents(float min, float max)
Set the displayed minimum and maximum values for the y axis to the given range, if supported.
virtual QColor getForeground() const
virtual void toXml(QTextStream &stream, QString indent="", QString extraAttributes="") const
Convert the layer's data (though not those of the model it refers to) into XML for file output.
void setNormalizeHybrid(bool n)
Normalize each column to its maximum value, and then scale by the log of the (absolute) maximum value...
virtual ViewManager * getViewManager() const
float getYForBin(View *, float bin) const
Return the y coordinate at which the given bin "starts" (i.e.
int getColourScaleWidth(QPainter &) const
virtual int getPropertyRangeAndValue(const PropertyName &, int *min, int *max, int *deflt) const
void setColourMap(int map)
virtual bool getValueExtents(float &min, float &max, bool &logarithmic, QString &unit) const
Return the minimum and maximum values for the y axis of the model in this layer, as well as whether t...
virtual bool shouldIlluminateLocalFeatures(const Layer *, QPoint &) const
static int getColourMapCount()
ColourScale m_colourScale
void setInvertVertical(bool i)
virtual void paintVerticalScale(View *v, bool, QPainter &paint, QRect rect) const
virtual QString getPropertyGroupName(const PropertyName &) const
bool getNormalizeColumns() const
virtual void setLayerDormant(const View *v, bool dormant)
Indicate that a layer is not currently visible in the given view and is not expected to become visibl...
int getZoomLevel() const
Return the zoom level, i.e.
virtual void toXml(QTextStream &stream, QString indent="", QString extraAttributes="") const
Convert the layer's data (though not those of the model it refers to) into XML for file output.
void setModel(const DenseThreeDimensionalModel *model)
void modelChangedWithin(int, int)
void setGain(float gain)
Set the gain multiplier for sample values in this view.
void setNormalizeVisibleArea(bool n)
Normalize each value against the maximum in the visible region.
virtual RangeMapper * getNewPropertyRangeMapper(const PropertyName &) const
virtual int getVerticalScaleWidth(View *v, bool, QPainter &) const
virtual QString getFeatureDescription(View *v, QPoint &) const
virtual bool getDisplayExtents(float &min, float &max) const
Return the minimum and maximum values within the displayed range for the y axis, if only a subset of ...
virtual QString getPropertyLabel(const PropertyName &) const
virtual void setVerticalZoomStep(int)
Set the vertical zoom step.
void layerParametersChanged()
void setNormalizeColumns(bool n)
Normalize each column to its maximum value, independent of its neighbours.
void sliceableModelReplaced(const Model *modelToBeReplaced, const Model *replacement)
A class for mapping intensity values onto various colour maps.
QColor map(float value) const
virtual RangeMapper * getNewVerticalZoomRangeMapper() const
Create and return a range mapper for vertical zoom step values.
virtual void setProperty(const PropertyName &, int value)
virtual bool isLayerScrollable(const View *v) const
This should return true if the layer can safely be scrolled automatically by a given view (simply cop...
bool getNormalizeVisibleArea() const
virtual void setLayerDormant(const View *v, bool dormant)
Indicate that a layer is not currently visible in the given view and is not expected to become visibl...
void setBinScale(BinScale)
Specify the scale for the y axis.
const DenseThreeDimensionalModel * m_model
View is the base class of widgets that display one or more overlaid views of data against a horizonta...
virtual void copy(View *, Selection, Clipboard &)
void setColourScale(ColourScale)
virtual void setProperties(const QXmlAttributes &)
Set the particular properties of a layer (those specific to the subclass) from a set of XML attribute...
bool m_normalizeVisibleArea
virtual void drawVisibleText(QPainter &p, int x, int y, QString text, TextStyle style) const
DenseThreeDimensionalModel::Column getColumn(int col) const
bool getInvertVertical() const
virtual QString getPropertyIconName(const PropertyName &) const
virtual int getCurrentVerticalZoomStep() const
Get the current vertical zoom step.
void paintDense(View *v, QPainter &paint, QRect rect) const
virtual bool snapToFeatureFrame(View *v, int &frame, int &resolution, SnapType snap) const
Adjust the given frame to snap to the nearest feature, if possible.
virtual QColor getBackground() const
virtual bool isLayerDormant(const View *v) const
Return whether the layer is dormant (i.e.
virtual QString getPropertyValueLabel(const PropertyName &, int value) const
float getBinForY(View *, float y) const
Return the bin number, possibly fractional, at the given y coordinate.
int getXForFrame(int frame) const
Return the pixel x-coordinate corresponding to a given sample frame (which may be negative).
virtual void paint(View *v, QPainter &paint, QRect rect) const
Paint the given rectangle of this layer onto the given view using the given painter,...
static QString getColourMapName(int n)
BinScale getBinScale() const