Mercurial > hg > svgui
comparison layer/Colour3DPlotLayer.cpp @ 469:9863f9a36cc2
* some tweaks that make Colour3DPlotLayer a little bit faster for
very dense models
author | Chris Cannam |
---|---|
date | Fri, 23 Jan 2009 15:11:40 +0000 |
parents | 762e96217900 |
children | 26d1ddc0ce96 |
comparison
equal
deleted
inserted
replaced
468:762e96217900 | 469:9863f9a36cc2 |
---|---|
34 | 34 |
35 | 35 |
36 Colour3DPlotLayer::Colour3DPlotLayer() : | 36 Colour3DPlotLayer::Colour3DPlotLayer() : |
37 m_model(0), | 37 m_model(0), |
38 m_cache(0), | 38 m_cache(0), |
39 m_peaksCache(0), | |
40 m_peakResolution(128), | |
39 m_cacheValidStart(0), | 41 m_cacheValidStart(0), |
40 m_cacheValidEnd(0), | 42 m_cacheValidEnd(0), |
41 m_colourScale(LinearScale), | 43 m_colourScale(LinearScale), |
42 m_colourScaleSet(false), | 44 m_colourScaleSet(false), |
43 m_colourMap(0), | 45 m_colourMap(0), |
52 } | 54 } |
53 | 55 |
54 Colour3DPlotLayer::~Colour3DPlotLayer() | 56 Colour3DPlotLayer::~Colour3DPlotLayer() |
55 { | 57 { |
56 delete m_cache; | 58 delete m_cache; |
59 delete m_peaksCache; | |
57 } | 60 } |
58 | 61 |
59 void | 62 void |
60 Colour3DPlotLayer::setModel(const DenseThreeDimensionalModel *model) | 63 Colour3DPlotLayer::setModel(const DenseThreeDimensionalModel *model) |
61 { | 64 { |
75 } | 78 } |
76 | 79 |
77 void | 80 void |
78 Colour3DPlotLayer::cacheInvalid() | 81 Colour3DPlotLayer::cacheInvalid() |
79 { | 82 { |
80 delete m_cache; | 83 delete m_cache; |
84 delete m_peaksCache; | |
81 m_cache = 0; | 85 m_cache = 0; |
86 m_peaksCache = 0; | |
82 m_cacheValidStart = 0; | 87 m_cacheValidStart = 0; |
83 m_cacheValidEnd = 0; | 88 m_cacheValidEnd = 0; |
84 } | 89 } |
85 | 90 |
86 void | 91 void |
719 size_t cacheWidth = modelEndBin - modelStartBin + 1; | 724 size_t cacheWidth = modelEndBin - modelStartBin + 1; |
720 size_t cacheHeight = m_model->getHeight(); | 725 size_t cacheHeight = m_model->getHeight(); |
721 | 726 |
722 if (m_cache && (m_cache->height() != int(cacheHeight))) { | 727 if (m_cache && (m_cache->height() != int(cacheHeight))) { |
723 delete m_cache; | 728 delete m_cache; |
729 delete m_peaksCache; | |
724 m_cache = 0; | 730 m_cache = 0; |
731 m_peaksCache = 0; | |
725 } | 732 } |
726 | 733 |
727 if (m_cache && (m_cache->width() != int(cacheWidth))) { | 734 if (m_cache && (m_cache->width() != int(cacheWidth))) { |
728 QImage *newCache = new QImage(m_cache->copy(0, 0, cacheWidth, cacheHeight)); | 735 QImage *newCache = |
736 new QImage(m_cache->copy(0, 0, cacheWidth, cacheHeight)); | |
729 delete m_cache; | 737 delete m_cache; |
730 m_cache = newCache; | 738 m_cache = newCache; |
739 if (m_peaksCache) { | |
740 QImage *newPeaksCache = | |
741 new QImage(m_peaksCache->copy | |
742 (0, 0, cacheWidth / m_peakResolution, cacheHeight)); | |
743 delete m_peaksCache; | |
744 m_peaksCache = newPeaksCache; | |
745 } | |
731 } | 746 } |
732 | 747 |
733 if (!m_cache) { | 748 if (!m_cache) { |
734 m_cache = new QImage(cacheWidth, cacheHeight, QImage::Format_Indexed8); | 749 m_cache = new QImage |
750 (cacheWidth, cacheHeight, QImage::Format_Indexed8); | |
735 m_cache->setNumColors(256); | 751 m_cache->setNumColors(256); |
752 if (modelResolution < m_peakResolution / 2 && !m_normalizeVisibleArea) { | |
753 m_peaksCache = new QImage | |
754 (cacheWidth / m_peakResolution + 1, cacheHeight, | |
755 QImage::Format_Indexed8); | |
756 m_peaksCache->setNumColors(256); | |
757 } else if (m_peaksCache) { | |
758 delete m_peaksCache; | |
759 m_peaksCache = 0; | |
760 } | |
736 m_cacheValidStart = 0; | 761 m_cacheValidStart = 0; |
737 m_cacheValidEnd = 0; | 762 m_cacheValidEnd = 0; |
738 } | 763 } |
739 | 764 |
740 if (m_cacheValidStart <= firstBin && m_cacheValidEnd >= lastBin) { | 765 if (m_cacheValidStart <= firstBin && m_cacheValidEnd >= lastBin) { |
789 | 814 |
790 ColourMapper mapper(m_colourMap, 0.f, 255.f); | 815 ColourMapper mapper(m_colourMap, 0.f, 255.f); |
791 | 816 |
792 for (int index = 0; index < 256; ++index) { | 817 for (int index = 0; index < 256; ++index) { |
793 QColor colour = mapper.map(index); | 818 QColor colour = mapper.map(index); |
794 m_cache->setColor(index, qRgb(colour.red(), colour.green(), colour.blue())); | 819 m_cache->setColor |
820 (index, qRgb(colour.red(), colour.green(), colour.blue())); | |
821 if (m_peaksCache) { | |
822 m_peaksCache->setColor | |
823 (index, qRgb(colour.red(), colour.green(), colour.blue())); | |
824 } | |
795 } | 825 } |
796 | 826 |
797 // m_cache->fill(0); | 827 // m_cache->fill(0); |
798 | 828 |
799 float visibleMax = 0.f, visibleMin = 0.f; | 829 float visibleMax = 0.f, visibleMin = 0.f; |
823 } | 853 } |
824 } | 854 } |
825 | 855 |
826 if (visibleMin == visibleMax) visibleMax = visibleMin + 1; | 856 if (visibleMin == visibleMax) visibleMax = visibleMin + 1; |
827 | 857 |
858 int *peaks = 0; | |
859 if (m_peaksCache) { | |
860 peaks = new int[cacheHeight]; | |
861 for (int y = 0; y < cacheHeight; ++y) { | |
862 peaks[y] = 0; | |
863 } | |
864 } | |
865 | |
828 for (size_t c = fillStart; c <= fillEnd; ++c) { | 866 for (size_t c = fillStart; c <= fillEnd; ++c) { |
829 | 867 |
830 values = getColumn(c); | 868 values = getColumn(c); |
831 | 869 |
832 for (size_t y = 0; y < cacheHeight; ++y) { | 870 for (size_t y = 0; y < cacheHeight; ++y) { |
833 | 871 |
834 float value = min; | 872 float value = min; |
835 if (y < values.size()) { | 873 if (y < values.size()) { |
836 value = values[y]; | 874 value = values.at(y); |
837 } | 875 } |
838 | 876 |
839 if (m_colourScale == LogScale) { | 877 if (m_colourScale == LogScale) { |
840 value = LogRange::map(value); | 878 value = LogRange::map(value); |
841 } | 879 } |
846 } | 884 } |
847 | 885 |
848 int pixel = int(((value - min) * 256) / (max - min)); | 886 int pixel = int(((value - min) * 256) / (max - min)); |
849 if (pixel < 0) pixel = 0; | 887 if (pixel < 0) pixel = 0; |
850 if (pixel > 255) pixel = 255; | 888 if (pixel > 255) pixel = 255; |
889 if (peaks && (pixel > peaks[y])) peaks[y] = pixel; | |
851 | 890 |
852 if (m_invertVertical) { | 891 if (m_invertVertical) { |
853 m_cache->setPixel(c, cacheHeight - y - 1, pixel); | 892 m_cache->setPixel(c, cacheHeight - y - 1, pixel); |
854 } else { | 893 } else { |
855 m_cache->setPixel(c, y, pixel); | 894 m_cache->setPixel(c, y, pixel); |
856 } | 895 } |
857 } | 896 } |
858 } | 897 |
898 if (peaks) { | |
899 size_t notch = (c % m_peakResolution); | |
900 if (notch == m_peakResolution-1 || c == fillEnd) { | |
901 size_t pc = c / m_peakResolution; | |
902 for (size_t y = 0; y < cacheHeight; ++y) { | |
903 if (m_invertVertical) { | |
904 m_peaksCache->setPixel(pc, cacheHeight - y - 1, peaks[y]); | |
905 } else { | |
906 m_peaksCache->setPixel(pc, y, peaks[y]); | |
907 } | |
908 } | |
909 for (int y = 0; y < cacheHeight; ++y) { | |
910 peaks[y] = 0; | |
911 } | |
912 } | |
913 } | |
914 } | |
915 | |
916 delete[] peaks; | |
859 } | 917 } |
860 | 918 |
861 void | 919 void |
862 Colour3DPlotLayer::paint(View *v, QPainter &paint, QRect rect) const | 920 Colour3DPlotLayer::paint(View *v, QPainter &paint, QRect rect) const |
863 { | 921 { |
927 std::cerr << "Colour3DPlotLayer::paint: height = "<< m_model->getHeight() << ", modelStart = " << modelStart << ", resolution = " << modelResolution << ", model rate = " << m_model->getSampleRate() << " (zoom level = " << v->getZoomLevel() << ", srRatio = " << srRatio << ")" << std::endl; | 985 std::cerr << "Colour3DPlotLayer::paint: height = "<< m_model->getHeight() << ", modelStart = " << modelStart << ", resolution = " << modelResolution << ", model rate = " << m_model->getSampleRate() << " (zoom level = " << v->getZoomLevel() << ", srRatio = " << srRatio << ")" << std::endl; |
928 #endif | 986 #endif |
929 | 987 |
930 if (m_opaque || | 988 if (m_opaque || |
931 int(m_model->getHeight()) >= v->height() || | 989 int(m_model->getHeight()) >= v->height() || |
932 // int(modelResolution * m_model->getSampleRate()) < v->getZoomLevel() / 2) { | |
933 ((modelResolution * srRatio) / v->getZoomLevel()) < 2) { | 990 ((modelResolution * srRatio) / v->getZoomLevel()) < 2) { |
934 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT | 991 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT |
935 std::cerr << "calling paintDense" << std::endl; | 992 std::cerr << "calling paintDense" << std::endl; |
936 #endif | 993 #endif |
937 paintDense(v, paint, rect); | 994 paintDense(v, paint, rect); |
1029 if (!m_cache) return; | 1086 if (!m_cache) return; |
1030 | 1087 |
1031 float modelStart = m_model->getStartFrame(); | 1088 float modelStart = m_model->getStartFrame(); |
1032 float modelResolution = m_model->getResolution(); | 1089 float modelResolution = m_model->getResolution(); |
1033 | 1090 |
1034 float srRatio = | 1091 int mmsr = v->getViewManager()->getMainModelSampleRate(); |
1035 float(v->getViewManager()->getMainModelSampleRate()) / | 1092 int msr = m_model->getSampleRate(); |
1036 float(m_model->getSampleRate()); | 1093 float srRatio = float(mmsr) / float(msr); |
1037 | 1094 |
1038 int x0 = rect.left(); | 1095 int x0 = rect.left(); |
1039 int x1 = rect.right() + 1; | 1096 int x1 = rect.right() + 1; |
1040 | 1097 |
1041 int w = x1 - x0; | 1098 int w = x1 - x0; |
1055 img.setColorTable(m_cache->colorTable()); | 1112 img.setColorTable(m_cache->colorTable()); |
1056 | 1113 |
1057 uchar *peaks = new uchar[w]; | 1114 uchar *peaks = new uchar[w]; |
1058 memset(peaks, 0, w); | 1115 memset(peaks, 0, w); |
1059 | 1116 |
1117 int zoomLevel = v->getZoomLevel(); | |
1118 | |
1119 QImage *source = m_cache; | |
1120 if (m_peaksCache && | |
1121 ((modelResolution * srRatio * m_peakResolution) / zoomLevel) < 1) { | |
1122 // std::cerr << "using peaks cache" << std::endl; | |
1123 source = m_peaksCache; | |
1124 modelResolution *= m_peakResolution; | |
1125 } else { | |
1126 // std::cerr << "not using peaks cache" << std::endl; | |
1127 } | |
1128 | |
1060 int psy1i = -1; | 1129 int psy1i = -1; |
1130 int sw = source->width(); | |
1061 | 1131 |
1062 for (int y = 0; y < h; ++y) { | 1132 for (int y = 0; y < h; ++y) { |
1063 | 1133 |
1064 float sy0 = symin + (float(h - y - 1) * (symax - symin)) / h; | 1134 float sy0 = symin + (float(h - y - 1) * (symax - symin)) / h; |
1065 float sy1 = symin + (float(h - y) * (symax - symin)) / h; | 1135 float sy1 = symin + (float(h - y) * (symax - symin)) / h; |
1075 | 1145 |
1076 memset(peaks, 0, w); | 1146 memset(peaks, 0, w); |
1077 | 1147 |
1078 for (int sy = sy0i; sy <= sy1i; ++sy) { | 1148 for (int sy = sy0i; sy <= sy1i; ++sy) { |
1079 | 1149 |
1080 if (sy < 0 || sy >= m_cache->height()) continue; | 1150 if (sy < 0 || sy >= source->height()) continue; |
1081 | 1151 |
1082 uchar *sourceLine = m_cache->scanLine(sy); | 1152 uchar *sourceLine = source->scanLine(sy); |
1083 | 1153 |
1084 long xf = -1, nxf = -1; | 1154 long xf = -1; |
1155 long nxf = v->getFrameForX(x0); | |
1156 | |
1157 int nsxi = -1; | |
1085 | 1158 |
1086 for (int x = 0; x < w; ++x) { | 1159 for (int x = 0; x < w; ++x) { |
1087 | 1160 |
1088 xf = nxf; | 1161 xf = nxf; |
1089 nxf = v->getFrameForX(x + 1 + x0); | 1162 nxf = xf + zoomLevel; |
1090 | |
1091 if (xf < 0) { | |
1092 xf = v->getFrameForX(x + x0); | |
1093 } | |
1094 | 1163 |
1095 if (xf < 0) { | 1164 if (xf < 0) { |
1096 peaks[x] = 0; | 1165 peaks[x] = 0; |
1097 continue; | 1166 continue; |
1098 } | 1167 } |
1103 int sx0i = int(sx0 + 0.001); | 1172 int sx0i = int(sx0 + 0.001); |
1104 int sx1i = int(sx1); | 1173 int sx1i = int(sx1); |
1105 | 1174 |
1106 uchar peak = 0; | 1175 uchar peak = 0; |
1107 for (int sx = sx0i; sx <= sx1i; ++sx) { | 1176 for (int sx = sx0i; sx <= sx1i; ++sx) { |
1108 if (sx < 0 || sx >= m_cache->width()) continue; | 1177 if (sx < 0 || sx >= sw) continue; |
1109 if (sourceLine[sx] > peak) peak = sourceLine[sx]; | 1178 if (sourceLine[sx] > peak) peak = sourceLine[sx]; |
1110 } | 1179 } |
1111 peaks[x] = peak; | 1180 peaks[x] = peak; |
1112 } | 1181 } |
1113 } | 1182 } |
1115 copy: | 1184 copy: |
1116 for (int x = 0; x < w; ++x) { | 1185 for (int x = 0; x < w; ++x) { |
1117 targetLine[x] = peaks[x]; | 1186 targetLine[x] = peaks[x]; |
1118 } | 1187 } |
1119 } | 1188 } |
1189 | |
1190 delete[] peaks; | |
1120 | 1191 |
1121 paint.drawImage(x0, 0, img); | 1192 paint.drawImage(x0, 0, img); |
1122 } | 1193 } |
1123 | 1194 |
1124 bool | 1195 bool |