10#include "qwt_plot_spectrogram.h"
11#include "qwt_painter.h"
12#include "qwt_interval.h"
13#include "qwt_scale_map.h"
14#include "qwt_color_map.h"
22#include <qtconcurrentrun.h>
27#include <qelapsedtimer.h>
32static inline bool qwtIsNaN(
double d )
37 const uchar* ch = (
const uchar*)&d;
38 if ( QSysInfo::ByteOrder == QSysInfo::BigEndian )
40 return ( ch[0] & 0x7f ) == 0x7f && ch[1] > 0xf0;
44 return ( ch[7] & 0x7f ) == 0x7f && ch[6] > 0xf0;
48class QwtPlotSpectrogram::PrivateData
70 void updateColorTable()
78 if ( colorTableSize == 0 )
81 colorTable = colorMap->
colorTable( colorTableSize );
90 QPen defaultContourPen;
111 m_data =
new PrivateData();
143 if ( on !=
bool( mode & m_data->displayMode ) )
146 m_data->displayMode |= mode;
148 m_data->displayMode &= ~mode;
163 return ( m_data->displayMode & mode );
184 delete m_data->colorMap;
188 m_data->updateColorTable();
202 return m_data->colorMap;
226 numColors = qMax( numColors, 0 );
227 if ( numColors != m_data->colorTableSize )
229 m_data->colorTableSize = numColors;
230 m_data->updateColorTable();
240 return m_data->colorTableSize;
257 const QColor& color, qreal width, Qt::PenStyle style )
274 if ( pen != m_data->defaultContourPen )
276 m_data->defaultContourPen = pen;
289 return m_data->defaultContourPen;
305 if ( m_data->data == NULL || m_data->colorMap == NULL )
309 const QColor c( m_data->colorMap->
rgb( intensityRange, level ) );
327 if (
bool( m_data->conrecFlags & flag ) == on )
331 m_data->conrecFlags |= flag;
333 m_data->conrecFlags &= ~flag;
353 return m_data->conrecFlags & flag;
367 m_data->contourLevels = levels;
368 std::sort( m_data->contourLevels.begin(), m_data->contourLevels.end() );
384 return m_data->contourLevels;
395 if (
data != m_data->data )
434 if ( m_data->data == NULL )
437 return m_data->data->
interval( axis );
458 if ( m_data->data == NULL )
482 const QRectF& area,
const QSize& imageSize )
const
484 if ( imageSize.isEmpty() || m_data->data == NULL
485 || m_data->colorMap == NULL )
491 if ( !intensityRange.
isValid() )
494 const QImage::Format format = ( m_data->colorMap->format() ==
QwtColorMap::RGB )
495 ? QImage::Format_ARGB32 : QImage::Format_Indexed8;
497 QImage image( imageSize, format );
502 m_data->data->
initRaster( area, image.size() );
509#if !defined( QT_NO_QFUTURE )
512 if ( numThreads <= 0 )
513 numThreads = QThread::idealThreadCount();
515 if ( numThreads <= 0 )
518 const int numRows = imageSize.height() / numThreads;
521 futures.reserve( numThreads - 1 );
523 for ( uint i = 0; i < numThreads; i++ )
525 QRect tile( 0, i * numRows, image.width(), numRows );
526 if ( i == numThreads - 1 )
528 tile.setHeight( image.height() - i * numRows );
533 futures += QtConcurrent::run(
534#
if QT_VERSION >= 0x060000
539 xMap, yMap, tile, &image );
543 for (
int i = 0; i < futures.size(); i++ )
544 futures[i].waitForFinished();
547 const QRect tile( 0, 0, image.width(), image.height() );
552 const qint64 elapsed = time.elapsed();
553 qDebug() <<
"renderImage" << imageSize << elapsed;
574 const QRect& tile, QImage* image )
const
577 if ( range.
width() <= 0.0 )
584 const int numColors = m_data->colorTable.size();
585 const QRgb* rgbTable = m_data->colorTable.constData();
588 for (
int y = tile.top(); y <= tile.bottom(); y++ )
592 QRgb* line =
reinterpret_cast< QRgb*
>( image->scanLine( y ) );
595 for (
int x = tile.left(); x <= tile.right(); x++ )
599 const double value = m_data->data->
value( tx, ty );
601 if ( hasGaps && qwtIsNaN( value ) )
605 else if ( numColors == 0 )
612 *line++ = rgbTable[index];
619 for (
int y = tile.top(); y <= tile.bottom(); y++ )
623 unsigned char* line = image->scanLine( y );
626 for (
int x = tile.left(); x <= tile.right(); x++ )
630 const double value = m_data->data->
value( tx, ty );
632 if ( hasGaps && qwtIsNaN( value ) )
638 const uint index = m_data->colorMap->
colorIndex( 256, range, value );
639 *line++ =
static_cast< unsigned char >( index );
664 const QRectF& area,
const QRect& rect )
const
666 QSize raster = rect.size() / 2;
668 const QRectF pixelRect =
pixelHint( area );
669 if ( !pixelRect.isEmpty() )
671 const QSize res( qwtCeil( rect.width() / pixelRect.width() ),
672 qwtCeil( rect.height() / pixelRect.height() ) );
673 raster = raster.boundedTo( res );
690 const QRectF& rect,
const QSize& raster )
const
692 if ( m_data->data == NULL )
696 m_data->contourLevels, m_data->conrecFlags );
713 if ( m_data->data == NULL )
716 const int numLevels = m_data->contourLevels.size();
717 for (
int l = 0; l < numLevels; l++ )
719 const double level = m_data->contourLevels[l];
722 if ( pen.style() == Qt::NoPen )
725 if ( pen.style() == Qt::NoPen )
728 painter->setPen( pen );
730 const QPolygonF& lines = contourLines[level];
731 for (
int i = 0; i < lines.size(); i += 2 )
733 const QPointF p1( xMap.
transform( lines[i].x() ),
735 const QPointF p2( xMap.
transform( lines[i + 1].x() ),
756 const QRectF& canvasRect )
const
764 const int margin = 2;
765 QRectF rasterRect( canvasRect.x() - margin, canvasRect.y() - margin,
766 canvasRect.width() + 2 * margin, canvasRect.height() + 2 * margin );
774 if ( area.isEmpty() )
781 raster = raster.boundedTo( rasterRect.toRect().size() );
782 if ( raster.isValid() )
QwtColorMap is used to map values into colors.
virtual uint colorIndex(int numColors, const QwtInterval &interval, double value) const
Map a value of a given interval into a color index.
@ RGB
The map is intended to map into RGB values.
virtual QVector< QRgb > colorTable(int numColors) const
virtual QVector< QRgb > colorTable256() const
virtual QRgb rgb(const QwtInterval &interval, double value) const =0
A class representing an interval.
double width() const
Return the width of an interval.
QwtLinearColorMap builds a color map from color stops.
static void drawLine(QPainter *, qreal x1, qreal y1, qreal x2, qreal y2)
Wrapper for QPainter::drawLine()
virtual void legendChanged()
void setZ(double z)
Set the z value.
void setItemAttribute(ItemAttribute, bool on=true)
@ Rtti_PlotSpectrogram
For QwtPlotSpectrogram.
virtual void itemChanged()
@ Legend
The item is represented on the legend.
uint renderThreadCount() const
A class, which displays raster data.
virtual void draw(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect) const override
Draw the raster data.
virtual QRectF boundingRect() const override
void setColorTableSize(int numColors)
virtual QPen contourPen(double level) const
Calculate the pen for a contour line.
QFlags< DisplayMode > DisplayModes
virtual QSize contourRasterSize(const QRectF &, const QRect &) const
Return the raster to be used by the CONREC contour algorithm.
virtual QwtRasterData::ContourLines renderContourLines(const QRectF &rect, const QSize &raster) const
QList< double > contourLevels() const
virtual QRectF pixelHint(const QRectF &) const override
Pixel hint.
void setDisplayMode(DisplayMode, bool on=true)
virtual QwtInterval interval(Qt::Axis) const override
void setColorMap(QwtColorMap *)
void setContourLevels(const QList< double > &)
void setData(QwtRasterData *data)
bool testConrecFlag(QwtRasterData::ConrecFlag) const
virtual void drawContourLines(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QwtRasterData::ContourLines &) const
void renderTile(const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRect &tile, QImage *) const
Render a tile of an image.
@ ContourMode
The data is displayed using contour lines.
@ ImageMode
The values are mapped to colors using a color map.
int colorTableSize() const
QwtPlotSpectrogram(const QString &title=QString())
const QwtRasterData * data() const
const QwtColorMap * colorMap() const
bool testDisplayMode(DisplayMode) const
virtual void draw(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect) const override
Draw the spectrogram.
void setConrecFlag(QwtRasterData::ConrecFlag, bool on)
virtual int rtti() const override
virtual ~QwtPlotSpectrogram()
Destructor.
void setDefaultContourPen(const QColor &, qreal width=0.0, Qt::PenStyle=Qt::SolidLine)
virtual QImage renderImage(const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &area, const QSize &imageSize) const override
Render an image from data and color map.
QPen defaultContourPen() const
QwtRasterData defines an interface to any type of raster data.
virtual QRectF pixelHint(const QRectF &) const
Pixel hint.
bool testAttribute(Attribute) const
QMap< double, QPolygonF > ContourLines
Contour lines.
QFlags< ConrecFlag > ConrecFlags
virtual void discardRaster()
Discard a raster.
virtual double value(double x, double y) const =0
virtual void initRaster(const QRectF &, const QSize &raster)
Initialize a raster.
virtual ContourLines contourLines(const QRectF &rect, const QSize &raster, const QList< double > &levels, ConrecFlags) const
virtual QwtInterval interval(Qt::Axis) const =0
ConrecFlag
Flags to modify the contour algorithm.
@ IgnoreOutOfRange
Ignore all values, that are out of range.
@ IgnoreAllVerticesOnLevel
Ignore all vertices on the same level.
double transform(double s) const
double invTransform(double p) const