comparison layer/Colour3DPlotLayer.cpp @ 0:2a4f26e85b4c

initial import
author Chris Cannam
date Tue, 10 Jan 2006 16:33:16 +0000
parents
children 37b110168acf
comparison
equal deleted inserted replaced
-1:000000000000 0:2a4f26e85b4c
1 /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 A waveform viewer and audio annotation editor.
5 Chris Cannam, Queen Mary University of London, 2005
6
7 This is experimental software. Not for distribution.
8 */
9
10 #include "Colour3DPlotLayer.h"
11
12 #include "base/View.h"
13 #include "base/Profiler.h"
14
15 #include <QPainter>
16 #include <QImage>
17 #include <QRect>
18
19 #include <iostream>
20
21 #include <cassert>
22
23
24 Colour3DPlotLayer::Colour3DPlotLayer(View *w) :
25 Layer(w),
26 m_model(0),
27 m_cache(0)
28 {
29 m_view->addLayer(this);
30 }
31
32 Colour3DPlotLayer::~Colour3DPlotLayer()
33 {
34 }
35
36 void
37 Colour3DPlotLayer::setModel(const DenseThreeDimensionalModel *model)
38 {
39 m_model = model;
40 if (!m_model || !m_model->isOK()) return;
41
42 connect(m_model, SIGNAL(modelChanged()), this, SIGNAL(modelChanged()));
43 connect(m_model, SIGNAL(modelChanged(size_t, size_t)),
44 this, SIGNAL(modelChanged(size_t, size_t)));
45
46 connect(m_model, SIGNAL(completionChanged()),
47 this, SIGNAL(modelCompletionChanged()));
48
49 connect(m_model, SIGNAL(modelChanged()), this, SLOT(cacheInvalid()));
50 connect(m_model, SIGNAL(modelChanged(size_t, size_t)),
51 this, SLOT(cacheInvalid(size_t, size_t)));
52
53 emit modelReplaced();
54 }
55
56 void
57 Colour3DPlotLayer::cacheInvalid()
58 {
59 delete m_cache;
60 m_cache = 0;
61 }
62
63 void
64 Colour3DPlotLayer::cacheInvalid(size_t, size_t)
65 {
66 cacheInvalid();
67 }
68
69 void
70 Colour3DPlotLayer::paint(QPainter &paint, QRect rect) const
71 {
72 // Profiler profiler("Colour3DPlotLayer::paint");
73 // std::cerr << "Colour3DPlotLayer::paint(): m_model is " << m_model << ", zoom level is " << m_view->getZoomLevel() << std::endl;
74
75 //!!! This doesn't yet accommodate the fact that the model may
76 //have a different sample rate from an underlying model. At the
77 //moment our paint mechanism assumes all models have the same
78 //sample rate. If that isn't the case, they won't align and the
79 //time ruler will match whichever model was used to construct it.
80 //Obviously it is not going to be the case in general that models
81 //will have the same samplerate, so we need a pane samplerate as
82 //well which we trivially realign to. (We can probably require
83 //the waveform and spectrogram layers to display at the pane
84 //samplerate.)
85
86 int completion = 0;
87 if (!m_model || !m_model->isOK() || !m_model->isReady(&completion)) {
88 if (completion > 0) {
89 paint.fillRect(0, 10, m_view->width() * completion / 100,
90 10, QColor(120, 120, 120));
91 }
92 return;
93 }
94
95 long startFrame = m_view->getStartFrame();
96 int zoomLevel = m_view->getZoomLevel();
97
98 size_t modelStart = m_model->getStartFrame();
99 size_t modelEnd = m_model->getEndFrame();
100 size_t modelWindow = m_model->getWindowSize();
101
102 if (!m_cache) {
103
104 m_cache = new QImage((modelEnd - modelStart) / modelWindow + 1,
105 m_model->getYBinCount(),
106 QImage::Format_Indexed8);
107
108 m_cache->setNumColors(256);
109 DenseThreeDimensionalModel::BinValueSet values;
110 /*
111 for (int pixel = 0; pixel < 256; ++pixel) {
112 int hue = 256 - pixel;
113 // int hue = 220 - pixel;
114 // if (hue < 0) hue += 360;
115 QColor color = QColor::fromHsv(hue, pixel/2 + 128, pixel);
116 m_cache->setColor(pixel, qRgb(color.red(), color.green(), color.blue()));
117 }
118 */
119
120 float min = m_model->getMinimumLevel();
121 float max = m_model->getMaximumLevel();
122
123 if (max == min) max = min + 1.0;
124
125 // int min = lrintf(m_model->getMinimumLevel());
126 // int max = lrintf(m_model->getMaximumLevel());
127 for (int value = 0; value < 256; ++value) {
128 // int spread = ((value - min) * 256) / (max - min);
129 // int hue = 256 - spread;
130 // QColor color = QColor::fromHsv(hue, spread/2 + 128, spread);
131 int hue = 256 - value;
132 QColor color = QColor::fromHsv(hue, value/2 + 128, value);
133 m_cache->setColor(value, qRgba(color.red(), color.green(), color.blue(), 80));
134 // std::cerr << "Colour3DPlotLayer: Index " << value << ": hue " << hue << std::endl;
135 }
136
137 m_cache->fill(min);
138
139 for (size_t f = modelStart; f <= modelEnd; f += modelWindow) {
140
141 values.clear();
142 m_model->getBinValues(f, values);
143
144 for (size_t y = 0; y < m_model->getYBinCount(); ++y) {
145
146 float value = min;
147 if (y < values.size()) value = values[y];
148
149 //!!! divide-by-zero!
150 int pixel = int(((value - min) * 256) / (max - min));
151
152 m_cache->setPixel(f / modelWindow, y, pixel);
153 }
154 }
155 }
156
157 int x0 = rect.left();
158 int x1 = rect.right() + 1;
159
160 // int y0 = rect.top();
161 // int y1 = rect.bottom();
162 int w = x1 - x0;
163 int h = m_view->height();
164
165 // The cache is from the model's start frame to the model's end
166 // frame at the model's window increment frames per pixel. We
167 // want to draw from our start frame + x0 * zoomLevel to our start
168 // frame + x1 * zoomLevel at zoomLevel frames per pixel.
169
170 //!!! Strictly speaking we want quite different paint mechanisms
171 //for models that have more than one bin per pixel in either
172 //direction. This one is only really appropriate for models with
173 //far fewer bins in both directions.
174
175 int sx0 = ((startFrame + x0 * zoomLevel) - int(modelStart)) /
176 int(modelWindow);
177 int sx1 = ((startFrame + x1 * zoomLevel) - int(modelStart)) /
178 int(modelWindow);
179 int sw = sx1 - sx0;
180 int sh = m_model->getYBinCount();
181
182 /*
183 std::cerr << "Colour3DPlotLayer::paint: w " << w << ", h " << h << ", sx0 " << sx0 << ", sx1 " << sx1 << ", sw " << sw << ", sh " << sh << std::endl;
184 std::cerr << "Colour3DPlotLayer: sample rate is " << m_model->getSampleRate() << ", window size " << m_model->getWindowSize() << std::endl;
185 */
186
187 for (int sx = sx0 - 1; sx <= sx1; ++sx) {
188
189 int fx = sx * int(modelWindow);
190
191 if (fx + modelWindow < int(modelStart) ||
192 fx > int(modelEnd)) continue;
193
194 for (int sy = 0; sy < sh; ++sy) {
195
196 int rx0 = ((fx + int(modelStart))
197 - int(startFrame)) / zoomLevel;
198 int rx1 = ((fx + int(modelWindow) + int(modelStart))
199 - int(startFrame)) / zoomLevel;
200
201 int ry0 = h - (sy * h) / sh - 1;
202 int ry1 = h - ((sy + 1) * h) / sh - 2;
203 QRgb pixel = qRgb(255, 255, 255);
204 if (sx >= 0 && sx < m_cache->width() &&
205 sy >= 0 && sy < m_cache->height()) {
206 pixel = m_cache->pixel(sx, sy);
207 }
208
209 QColor pen(255, 255, 255, 80);
210 // QColor pen(pixel);
211 QColor brush(pixel);
212 brush.setAlpha(160);
213 // paint.setPen(pen);
214 paint.setPen(Qt::NoPen);
215 paint.setBrush(brush);
216
217 int w = rx1 - rx0;
218 if (w < 1) w = 1;
219 paint.drawRect(rx0, ry0 - h / sh - 1, w, h / sh + 1);
220
221 if (sx >= 0 && sx < m_cache->width() &&
222 sy >= 0 && sy < m_cache->height()) {
223 int dv = m_cache->pixelIndex(sx, sy);
224 if (dv != 0 && paint.fontMetrics().height() < (h / sh)) {
225 QString text = QString("%1").arg(dv);
226 if (paint.fontMetrics().width(text) < w - 3) {
227 paint.setPen(Qt::white);
228 paint.drawText(rx0 + 2,
229 ry0 - h / sh - 1 + 2 + paint.fontMetrics().ascent(),
230 QString("%1").arg(dv));
231 }
232 }
233 }
234 }
235 }
236
237 /*
238 QRect targetRect(x0, 0, w, h);
239 QRect sourceRect(sx0, 0, sw, sh);
240
241 QImage scaled(w, h, QImage::Format_RGB32);
242
243 for (int x = 0; x < w; ++x) {
244 for (int y = 0; y < h; ++y) {
245
246
247
248 int sx = sx0 + (x * sw) / w;
249 int sy = sh - (y * sh) / h - 1;
250 // std::cerr << "Colour3DPlotLayer::paint: sx " << sx << ", sy " << sy << ", cache w " << m_cache->width() << ", cache h " << m_cache->height() << std::endl;
251 if (sx >= 0 && sy >= 0 &&
252 sx < m_cache->width() && sy < m_cache->height()) {
253 scaled.setPixel(x, y, m_cache->pixel(sx, sy));
254 } else {
255 scaled.setPixel(x, y, qRgba(255, 255, 255, 80));
256 }
257 }
258 }
259
260 paint.drawImage(x0, 0, scaled);
261 */
262 }
263
264 #ifdef INCLUDE_MOCFILES
265 #include "Colour3DPlotLayer.moc.cpp"
266 #endif
267
268