Skip to content

Commit

Permalink
use two draws for waterfall
Browse files Browse the repository at this point in the history
  • Loading branch information
yuzawa-san committed Oct 18, 2024
1 parent f56cfcf commit 22d2adc
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 24 deletions.
58 changes: 35 additions & 23 deletions src/qtgui/plotter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,7 @@ void CPlotter::resizeEvent(QResizeEvent* )

// New waterfall, create blank area
else if (m_WaterfallImage.isNull()) {
m_WaterfallImage = QImage(w, wfHeight * 2, QImage::Format_RGB32);
m_WaterfallImage = QImage(w, wfHeight, QImage::Format_RGB32);
m_WaterfallImage.setDevicePixelRatio(m_DPR);
m_WaterfallImage.fill(Qt::black);
m_WaterfallOffset = wfHeight;
Expand All @@ -1046,25 +1046,29 @@ void CPlotter::resizeEvent(QResizeEvent* )
// invalidate time
else
{
const int wfHeightOld = m_WaterfallImage.height();
QImage oldWaterfall = m_WaterfallImage.scaled(
w, m_WaterfallImage.height(),
w, wfHeightOld,
Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
m_WaterfallImage = QImage(w, wfHeight * 2, QImage::Format_RGB32);
m_WaterfallImage = QImage(w, wfHeight, QImage::Format_RGB32);
m_WaterfallImage.setDevicePixelRatio(m_DPR);
m_WaterfallImage.fill(Qt::black);
memcpy(m_WaterfallImage.scanLine(wfHeight), oldWaterfall.scanLine(m_WaterfallOffset),
m_WaterfallImage.bytesPerLine() * std::min(wfHeight, m_WaterfallHeight));
const int firstHeight = std::min(wfHeight, wfHeightOld - m_WaterfallOffset);
memcpy(m_WaterfallImage.scanLine(0), oldWaterfall.scanLine(m_WaterfallOffset),
m_WaterfallImage.bytesPerLine() * firstHeight);
const int secondHeight = std::min(wfHeight - firstHeight, m_WaterfallOffset);
memcpy(m_WaterfallImage.scanLine(firstHeight), oldWaterfall.scanLine(0),
m_WaterfallImage.bytesPerLine() * secondHeight);
m_WaterfallOffset = wfHeight;
}
m_WaterfallHeight = wfHeight;

// Invalidate on resize
m_MaxHoldValid = false;
m_MinHoldValid = false;
m_histIIRValid = false;
// Do not need to invalidate IIR data (just histogram IIR)

// Waterfall accumulator my be the wrong size now, so invalidate.
// Waterfall accumulator may be the wrong size now, so invalidate.
if (msec_per_wfline > 0)
clearWaterfallBuf();

Expand All @@ -1084,24 +1088,35 @@ void CPlotter::paintEvent(QPaintEvent *)

QPainter painter(this);

int plotWidthT = 0;
int plotHeightT = 0;
if (!m_2DPixmap.isNull())
{
const int plotWidthS = m_2DPixmap.width();
const int plotHeightS = m_2DPixmap.height();
const QRect plotRectS(0, 0, plotWidthS, plotHeightS);
const QRectF plotRectS(0.0, 0.0, plotWidthS, plotHeightS);

const int plotWidthT = qRound((qreal)plotWidthS / m_DPR);
plotWidthT = qRound((qreal)plotWidthS / m_DPR);
plotHeightT = qRound((qreal)plotHeightS / m_DPR);
const QRect plotRectT(0, 0, plotWidthT, plotHeightT);
const QRectF plotRectT(0.0, 0.0, plotWidthT, plotHeightT);

painter.drawPixmap(plotRectT, m_2DPixmap, plotRectS);
}

if (!m_WaterfallImage.isNull())
{
painter.drawImage(QPoint(0, plotHeightT), m_WaterfallImage,
QRect(0, m_WaterfallOffset, m_WaterfallImage.width(), m_WaterfallHeight));
const int wfWidth = m_WaterfallImage.width();
const int wfHeight = m_WaterfallImage.height();
const int firstHeightS = wfHeight - m_WaterfallOffset;
const qreal firstHeightT = firstHeightS / m_DPR;
const qreal secondHeightT = m_WaterfallOffset / m_DPR;
// draw the waterfall in two parts based on the location of the offset:
// the first draw is the section below the offset to be drawm at top
painter.drawImage(QRectF(0.0, plotHeightT, plotWidthT, firstHeightT), m_WaterfallImage,
QRectF(0.0, m_WaterfallOffset, wfWidth, firstHeightS));
// the second draw is the section above the offset to be drawn below
painter.drawImage(QRectF(0.0, plotHeightT + firstHeightT, plotWidthT, secondHeightT), m_WaterfallImage,
QRectF(0.0, 0.0, wfWidth, m_WaterfallOffset));
}
}

Expand Down Expand Up @@ -1411,17 +1426,10 @@ void CPlotter::draw(bool newData)
wf_valid_since_ms = tnow_ms;
tlast_wf_drawn_ms = tnow_ms;

// move current offset up one line
// if the offset was zero, copy the top half of the waterfall
// to the bottom half of the waterfall and reset offset
if(m_WaterfallOffset-- == 0)
{
memcpy(m_WaterfallImage.scanLine(m_WaterfallHeight + 1), m_WaterfallImage.scanLine(0),
m_WaterfallImage.bytesPerLine() * (m_WaterfallHeight - 1));
m_WaterfallOffset = m_WaterfallHeight;
}


// move the offset "up"
// this changes how the resulting waterfall is drawn
// it is more efficient than moving all of the image scan lines
m_WaterfallOffset--;
// draw new line of fft data at top of waterfall bitmap
// draw black areas where data will not be draw
memset(m_WaterfallImage.scanLine(m_WaterfallOffset), 0, m_WaterfallImage.bytesPerLine());
Expand All @@ -1444,6 +1452,10 @@ void CPlotter::draw(bool newData)
cidx = std::max(std::min(cidx, 255), 0);
m_WaterfallImage.setPixel(ix, m_WaterfallOffset, m_ColorTbl[255 - cidx].rgb());
}
if(m_WaterfallOffset == 0)
{
m_WaterfallOffset = m_WaterfallImage.height();
}

wf_avg_count = 0;
if (msec_per_wfline > 0)
Expand Down
1 change: 0 additions & 1 deletion src/qtgui/plotter.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,6 @@ public slots:
QPixmap m_OverlayPixmap; // Grid, axes ... things that need to be drawn infrequently
QPixmap m_PeakPixmap;
QImage m_WaterfallImage;
int m_WaterfallHeight;
int m_WaterfallOffset;
QColor m_ColorTbl[256];
QSize m_Size;
Expand Down

0 comments on commit 22d2adc

Please sign in to comment.