Colour3DPlotRenderer.h
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7  This file copyright 2006-2016 Chris Cannam and QMUL.
8 
9  This program is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 2 of the
12  License, or (at your option) any later version. See the file
13  COPYING included with this distribution for more information.
14 */
15 
16 #ifndef COLOUR_3D_PLOT_RENDERER_H
17 #define COLOUR_3D_PLOT_RENDERER_H
18 
19 #include "ColourScale.h"
20 #include "ScrollableImageCache.h"
22 
23 #include "base/ColumnOp.h"
24 #include "base/MagnitudeRange.h"
25 
26 #include "data/model/Model.h"
27 
28 #include <QRect>
29 #include <QPainter>
30 #include <QImage>
31 
33 class VerticalBinLayer;
34 class RenderTimer;
35 class Dense3DModelPeakCache;
36 class DenseThreeDimensionalModel;
37 
38 enum class BinDisplay {
39  AllBins,
40  PeakBins,
42 };
43 
44 enum class BinScale {
45  Linear,
46  Log
47 };
48 
50 {
51 public:
52  struct Sources {
53  Sources() : verticalBinLayer(0) { }
54 
55  // These must all outlive this class
57  ModelId source; // always; a DenseThreeDimensionalModel
58  ModelId fft; // optionally; an FFTModel; used for phase/peak-freq modes
59  std::vector<ModelId> peakCaches; // zero or more
60  };
61 
62  struct Parameters {
64  colourScale(ColourScale::Parameters()),
65  normalization(ColumnNormalization::None),
66  binDisplay(BinDisplay::AllBins),
67  binScale(BinScale::Linear),
68  alwaysOpaque(false),
69  interpolate(false),
70  invertVertical(false),
71  showDerivative(false),
72  scaleFactor(1.0),
73  colourRotation(0) { }
74 
79 
81  ColumnNormalization normalization;
82 
85 
88 
94 
101 
104 
108 
113  double scaleFactor;
114 
117  };
118 
119  Colour3DPlotRenderer(Sources sources, Parameters parameters) :
120  m_sources(sources),
121  m_params(parameters),
122  m_secondsPerXPixel(0.0),
123  m_secondsPerXPixelValid(false)
124  { }
125 
126  struct RenderResult {
132  QRect rendered;
133 
143  MagnitudeRange range;
144  };
145 
170  RenderResult render(const LayerGeometryProvider *v,
171  QPainter &paint, QRect rect);
172 
198  RenderResult renderTimeConstrained(const LayerGeometryProvider *v,
199  QPainter &paint, QRect rect);
200 
213  QRect getLargestUncachedRect(const LayerGeometryProvider *v);
214 
221  bool geometryChanged(const LayerGeometryProvider *v);
222 
229  return decideRenderType(v) != DirectTranslucent;
230  }
231 
237  QColor getColour(double value) const {
238  return m_params.colourScale.getColour(value, m_params.colourRotation);
239  }
240 
246  QRect findSimilarRegionExtents(QPoint point) const;
247 
248 private:
251 
252  // Draw buffer is the target of each partial repaint. It is always
253  // at view height (not model height) and is cleared and repainted
254  // on each fragment render. The only reason it's stored as a data
255  // member is to avoid reallocation.
256  QImage m_drawBuffer;
257 
258  // A temporary store of magnitude ranges per-column, used when
259  // rendering to the draw buffer. This always has the same length
260  // as the width of the draw buffer, and the x coordinates of the
261  // two containers are equivalent.
262  std::vector<MagnitudeRange> m_magRanges;
263 
264  // The image cache is our persistent record of the visible
265  // area. It is always the same size as the view (i.e. the paint
266  // size reported by the LayerGeometryProvider) and is scrolled and
267  // partially repainted internally as appropriate. A render request
268  // is carried out by repainting to cache (via the draw buffer) any
269  // area that is being requested but is not valid in the cache, and
270  // then repainting from cache to the requested painter.
272 
273  // The mag range cache is our record of the column magnitude
274  // ranges for each of the columns in the cache. It always has the
275  // same start frame and width as the image cache, and the column
276  // indices match up across both. Our cache update mechanism
277  // guarantees that every valid column in the image cache has a
278  // valid range in the magnitude cache, but not necessarily vice
279  // versa (as the image cache is limited to contiguous ranges).
281 
284 
285  RenderResult render(const LayerGeometryProvider *v,
286  QPainter &paint, QRect rect, bool timeConstrained);
287 
288  MagnitudeRange renderDirectTranslucent(const LayerGeometryProvider *v,
289  QPainter &paint, QRect rect);
290 
291  void renderToCachePixelResolution(const LayerGeometryProvider *v, int x0,
292  int repaintWidth, bool rightToLeft,
293  bool timeConstrained);
294 
295  void renderToCacheBinResolution(const LayerGeometryProvider *v, int x0,
296  int repaintWidth);
297 
298  int renderDrawBuffer(int w, int h,
299  const std::vector<int> &binforx,
300  const std::vector<double> &binfory,
301  int peakCacheIndex, // -1 => don't use a peak cache
302  bool rightToLeft,
303  bool timeConstrained);
304 
305  int renderDrawBufferPeakFrequencies(const LayerGeometryProvider *v,
306  int w, int h,
307  const std::vector<int> &binforx,
308  const std::vector<double> &binfory,
309  bool rightToLeft,
310  bool timeConstrained);
311 
312  void recreateDrawBuffer(int w, int h);
313  void clearDrawBuffer(int w, int h);
314 
315  enum RenderType {
318  DirectTranslucent
319  };
320 
321  RenderType decideRenderType(const LayerGeometryProvider *) const;
322 
323  QImage scaleDrawBufferImage(QImage source, int targetWidth, int targetHeight)
324  const;
325 
326  ColumnOp::Column getColumn(int sx, int minbin, int nbins,
327  std::shared_ptr<DenseThreeDimensionalModel> source) const;
328  ColumnOp::Column getColumnRaw(int sx, int minbin, int nbins,
329  std::shared_ptr<DenseThreeDimensionalModel> source) const;
330 
331  void getPreferredPeakCache(const LayerGeometryProvider *,
332  int &peakCacheIndex, int &binsPerPeak) const;
333 
334  void updateTimings(const RenderTimer &timer, int xPixelCount);
335 };
336 
337 #endif
338 
ColourScale colourScale
A complete ColourScale object by value, used for colour map conversion.
bool willRenderOpaque(const LayerGeometryProvider *v)
Return true if the rendering will be opaque.
double scaleFactor
Initial scale factor (e.g.
Map values within a range onto a set of colours, with a given distribution (linear, log etc) and optional colourmap rotation.
Definition: ColourScale.h:34
Interface for classes that provide geometry information (such as size, start frame, and a large number of other properties) about the disposition of a layer.
int colourRotation
Colourmap rotation, in the range 0-255.
bool interpolate
Whether to apply smoothing when rendering cells at more than one pixel per cell.
QRect rendered
The rect that was actually rendered.
Interface for layers in which the Y axis corresponds to bin number rather than scale value...
Colour3DPlotRenderer(Sources sources, Parameters parameters)
bool showDerivative
Whether to show the frame-to-frame difference instead of the actual value.
bool alwaysOpaque
Whether cells should always be opaque.
ColumnNormalization normalization
Type of column normalization.
bool invertVertical
Whether to render the whole caboodle upside-down.
ScrollableImageCache m_cache
A cached image for a view that scrolls horizontally, such as a spectrogram.
QColor getColour(double value) const
Return the colour corresponding to the given value.
A cached set of magnitude range records for a view that scrolls horizontally, such as a spectrogram...
MagnitudeRange range
The magnitude range of the data in the rendered area, after initial scaling (parameters.scaleFactor) and normalisation, for use in displaying colour scale etc.
const VerticalBinLayer * verticalBinLayer
std::vector< ModelId > peakCaches
BinScale binScale
Scale for vertical bin spacing (linear or logarithmic).
BinDisplay binDisplay
Selection of bins to display.
ScrollableMagRangeCache m_magCache
std::vector< MagnitudeRange > m_magRanges