summaryrefslogtreecommitdiff
path: root/gr-qtgui/lib/plot_raster.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gr-qtgui/lib/plot_raster.cc')
-rw-r--r--gr-qtgui/lib/plot_raster.cc350
1 files changed, 350 insertions, 0 deletions
diff --git a/gr-qtgui/lib/plot_raster.cc b/gr-qtgui/lib/plot_raster.cc
new file mode 100644
index 0000000000..76bff473e9
--- /dev/null
+++ b/gr-qtgui/lib/plot_raster.cc
@@ -0,0 +1,350 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012,2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <iostream>
+#include <qimage.h>
+#include <qpen.h>
+#include <qpainter.h>
+#include "qwt_painter.h"
+#include "qwt_scale_map.h"
+#include "qwt_color_map.h"
+#include "plot_raster.h"
+
+#if QWT_VERSION < 0x060000
+#include "qwt_double_interval.h"
+#endif
+
+typedef QVector<QRgb> QwtColorTable;
+
+class PlotTimeRasterImage: public QImage
+{
+ // This class hides some Qt3/Qt4 API differences
+public:
+ PlotTimeRasterImage(const QSize &size, QwtColorMap::Format format):
+ QImage(size, format == QwtColorMap::RGB
+ ? QImage::Format_ARGB32 : QImage::Format_Indexed8 )
+ {
+ }
+
+ PlotTimeRasterImage(const QImage &other):
+ QImage(other)
+ {
+ }
+
+ void initColorTable(const QImage& other)
+ {
+ setColorTable(other.colorTable());
+ }
+};
+
+class PlotTimeRaster::PrivateData
+{
+public:
+ PrivateData()
+ {
+ data = NULL;
+ colorMap = new QwtLinearColorMap();
+ }
+
+ ~PrivateData()
+ {
+ delete colorMap;
+ }
+
+ TimeRasterData *data;
+ QwtColorMap *colorMap;
+};
+
+/*!
+ Sets the following item attributes:
+ - QwtPlotItem::AutoScale: true
+ - QwtPlotItem::Legend: false
+
+ The z value is initialized to 8.0.
+
+ \param title Title
+
+ \sa QwtPlotItem::setItemAttribute(), QwtPlotItem::setZ()
+*/
+PlotTimeRaster::PlotTimeRaster(const QString &title)
+ : QwtPlotRasterItem(title)
+{
+ d_data = new PrivateData();
+
+ setItemAttribute(QwtPlotItem::AutoScale, true);
+ setItemAttribute(QwtPlotItem::Legend, false);
+
+ setZ(1.0);
+}
+
+//! Destructor
+PlotTimeRaster::~PlotTimeRaster()
+{
+ delete d_data;
+}
+
+const TimeRasterData*
+PlotTimeRaster::data()const
+{
+ return d_data->data;
+}
+
+void
+PlotTimeRaster::setData(TimeRasterData *data)
+{
+ d_data->data = data;
+}
+
+//! \return QwtPlotItem::Rtti_PlotSpectrogram
+int
+PlotTimeRaster::rtti() const
+{
+ return QwtPlotItem::Rtti_PlotGrid;
+}
+
+/*!
+ Change the color map
+
+ Often it is useful to display the mapping between intensities and
+ colors as an additional plot axis, showing a color bar.
+
+ \param map Color Map
+
+ \sa colorMap(), QwtScaleWidget::setColorBarEnabled(),
+ QwtScaleWidget::setColorMap()
+*/
+void
+PlotTimeRaster::setColorMap(const QwtColorMap *map)
+{
+ delete d_data->colorMap;
+ d_data->colorMap = (QwtColorMap*)map;
+
+ invalidateCache();
+ itemChanged();
+}
+
+/*!
+ \return Color Map used for mapping the intensity values to colors
+ \sa setColorMap()
+*/
+const QwtColorMap &PlotTimeRaster::colorMap() const
+{
+ return *d_data->colorMap;
+}
+
+/*!
+ \return Bounding rect of the data
+ \sa QwtRasterData::boundingRect
+*/
+#if QWT_VERSION < 0x060000
+QwtDoubleRect PlotTimeRaster::boundingRect() const
+{
+ return d_data->data->boundingRect();
+}
+#endif
+
+/*!
+ \brief Returns the recommended raster for a given rect.
+
+ F.e the raster hint is used to limit the resolution of
+ the image that is rendered.
+
+ \param rect Rect for the raster hint
+ \return data().rasterHint(rect)
+*/
+#if QWT_VERSION < 0x060000
+QSize PlotTimeRaster::rasterHint(const QwtDoubleRect &rect) const
+{
+ return d_data->data->rasterHint(rect);
+}
+#endif
+
+/*!
+ \brief Render an image from the data and color map.
+
+ The area is translated into a rect of the paint device.
+ For each pixel of this rect the intensity is mapped
+ into a color.
+
+ \param xMap X-Scale Map
+ \param yMap Y-Scale Map
+ \param area Area that should be rendered in scale coordinates.
+
+ \return A QImage::Format_Indexed8 or QImage::Format_ARGB32 depending
+ on the color map.
+
+ \sa QwtRasterData::intensity(), QwtColorMap::rgb(),
+ QwtColorMap::colorIndex()
+*/
+#if QWT_VERSION < 0x060000
+QImage PlotTimeRaster::renderImage(const QwtScaleMap &xMap,
+ const QwtScaleMap &yMap,
+ const QwtDoubleRect &area) const
+#else
+QImage PlotTimeRaster::renderImage(const QwtScaleMap &xMap,
+ const QwtScaleMap &yMap,
+ const QRectF &area,
+ const QSize &size) const
+#endif
+{
+ if(area.isEmpty())
+ return QImage();
+
+#if QWT_VERSION < 0x060000
+ QRect rect = transform(xMap, yMap, area);
+ const QSize res = d_data->data->rasterHint(area);
+#else
+ QRect rect = QwtScaleMap::transform(xMap, yMap, area).toRect();
+ const QSize res(-1,-1);
+
+#endif
+
+ QwtScaleMap xxMap = xMap;
+ QwtScaleMap yyMap = yMap;
+
+ if(res.isValid()) {
+ /*
+ It is useless to render an image with a higher resolution
+ than the data offers. Of course someone will have to
+ scale this image later into the size of the given rect, but f.e.
+ in case of postscript this will done on the printer.
+ */
+ rect.setSize(rect.size().boundedTo(res));
+
+ int px1 = rect.x();
+ int px2 = rect.x() + rect.width();
+ if(xMap.p1() > xMap.p2())
+ qSwap(px1, px2);
+
+ double sx1 = area.x();
+ double sx2 = area.x() + area.width();
+ if(xMap.s1() > xMap.s2())
+ qSwap(sx1, sx2);
+
+ int py1 = rect.y();
+ int py2 = rect.y() + rect.height();
+ if(yMap.p1() > yMap.p2())
+ qSwap(py1, py2);
+
+ double sy1 = area.y();
+ double sy2 = area.y() + area.height();
+ if(yMap.s1() > yMap.s2())
+ qSwap(sy1, sy2);
+
+ xxMap.setPaintInterval(px1, px2);
+ xxMap.setScaleInterval(sx1, sx2);
+ yyMap.setPaintInterval(py1, py2);
+ yyMap.setScaleInterval(sy1, sy2);
+ }
+
+ PlotTimeRasterImage image(rect.size(), d_data->colorMap->format());
+
+#if QWT_VERSION < 0x060000
+ const QwtDoubleInterval intensityRange = d_data->data->range();
+#else
+ const QwtInterval intensityRange = d_data->data->interval(Qt::ZAxis);
+#endif
+ if(!intensityRange.isValid())
+ return image;
+
+ d_data->data->initRaster(area, rect.size());
+
+ if(d_data->colorMap->format() == QwtColorMap::RGB) {
+ for(int y = rect.top(); y <= rect.bottom(); y++) {
+ const double ty = yyMap.invTransform(y);
+
+ QRgb *line = (QRgb *)image.scanLine(y - rect.top());
+
+ for(int x = rect.left(); x <= rect.right(); x++) {
+ const double tx = xxMap.invTransform(x);
+
+ *line++ = d_data->colorMap->rgb(intensityRange,
+ d_data->data->value(tx, ty));
+ }
+ }
+ d_data->data->incrementResidual();
+ }
+ else if(d_data->colorMap->format() == QwtColorMap::Indexed) {
+ image.setColorTable(d_data->colorMap->colorTable(intensityRange));
+
+ for(int y = rect.top(); y <= rect.bottom(); y++) {
+ const double ty = yyMap.invTransform(y);
+
+ unsigned char *line = image.scanLine(y - rect.top());
+ for(int x = rect.left(); x <= rect.right(); x++) {
+ const double tx = xxMap.invTransform(x);
+
+ *line++ = d_data->colorMap->colorIndex(intensityRange,
+ d_data->data->value(tx, ty));
+ }
+ }
+ }
+
+ d_data->data->discardRaster();
+
+ // Mirror the image in case of inverted maps
+
+ const bool hInvert = xxMap.p1() > xxMap.p2();
+ const bool vInvert = yyMap.p1() > yyMap.p2();
+ if(hInvert || vInvert) {
+ image = image.mirrored(hInvert, vInvert);
+ }
+
+ return image;
+}
+
+#if QWT_VERSION < 0x060000
+QwtDoubleInterval
+PlotTimeRaster::interval(Qt::Axis ax) const
+{
+ return d_data->data->range();
+}
+
+#else
+
+QwtInterval
+PlotTimeRaster::interval(Qt::Axis ax) const
+{
+ return d_data->data->interval(ax);
+}
+#endif
+
+/*!
+ \brief Draw the raster
+
+ \param painter Painter
+ \param xMap Maps x-values into pixel coordinates.
+ \param yMap Maps y-values into pixel coordinates.
+ \param canvasRect Contents rect of the canvas in painter coordinates
+
+ \sa setDisplayMode, renderImage,
+ QwtPlotRasterItem::draw, drawContourLines
+*/
+
+void PlotTimeRaster::draw(QPainter *painter,
+ const QwtScaleMap &xMap,
+ const QwtScaleMap &yMap,
+ const QRect &canvasRect) const
+{
+ QwtPlotRasterItem::draw(painter, xMap, yMap, canvasRect);
+}
+