]> git.sesse.net Git - nageru/commitdiff
Remove the QCustomPlot dependency.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Mon, 14 Nov 2022 23:07:06 +0000 (00:07 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Mon, 14 Nov 2022 23:12:42 +0000 (00:12 +0100)
This was becoming more a liability than an asset, so replace it with
some custom drawing code. It's not 100% as nice, but pretty close.

README
meson.build
nageru/analyzer.cpp
nageru/analyzer.ui
nageru/rgb_histogram.cpp [new file with mode: 0644]
nageru/rgb_histogram.h [new file with mode: 0644]

diff --git a/README b/README
index a565b3984775a0417e732b67c8e37a1eabeb4d1e..b4a6291983c247637963079a14e1f3416c74035a 100644 (file)
--- a/README
+++ b/README
@@ -53,8 +53,6 @@ Nageru currently needs:
 
  - Qt 5.5 or newer for the GUI.
 
- - QCustomPlot for the histogram display in the frame analyzer.
-
  - libmicrohttpd for the embedded web server.
 
  - x264 for encoding high-quality video suitable for streaming to end users.
@@ -114,7 +112,7 @@ Futatabi also needs:
 If on Debian bullsey or something similar, you can install everything you need
 with:
 
-  apt install qtbase5-dev libqt5opengl5-dev qt5-default libqcustomplot-dev \
+  apt install qtbase5-dev libqt5opengl5-dev qt5-default \
     pkg-config libmicrohttpd-dev libusb-1.0-0-dev libluajit-5.1-dev \
     libzita-resampler-dev libva-dev libavcodec-dev libavformat-dev \
     libswscale-dev libavresample-dev libmovit-dev libegl1-mesa-dev \
index a7ea6ae2eb770ebc4cb266eb3d00cc79da495868..c41990f3bc9ef2b3eee903931b7a11f9c20869ce 100644 (file)
@@ -22,7 +22,6 @@ libusbdep = dependency('libusb-1.0')
 luajitdep = dependency('luajit')
 movitdep = dependency('movit')
 protobufdep = dependency('protobuf')
-qcustomplotdep = cxx.find_library('qcustomplot')
 qt5deps = dependency('qt5', modules: ['Core', 'Gui', 'Widgets', 'OpenGLExtensions', 'OpenGL', 'Network'])
 sdl2_imagedep = dependency('SDL2_image', required: false)
 sdl2dep = dependency('sdl2', required: false)
@@ -78,7 +77,7 @@ nageru_srcs = []
 nageru_deps = [shareddep, qt5deps, libjpegdep, movitdep, protobufdep,
        vax11dep, vadrmdep, x11dep, libavformatdep, libswresampledep, libavcodecdep, libavutildep,
        libswscaledep, libusbdep, luajitdep, dldep, x264dep, svtav1dep, alsadep, zitaresamplerdep,
-       qcustomplotdep, threaddep, eigendep, srtdep, libdrmdep]
+       threaddep, eigendep, srtdep, libdrmdep]
 nageru_include_dirs = [include_directories('nageru')]
 nageru_link_with = []
 nageru_build_rpath = ''
@@ -189,7 +188,7 @@ nageru_link_with += protobuf_lib
 qt_files = qt5.preprocess(
        moc_headers: ['nageru/analyzer.h', 'nageru/clickable_label.h', 'nageru/compression_reduction_meter.h', 'nageru/correlation_meter.h',
                'nageru/ellipsis_label.h', 'nageru/glwidget.h', 'nageru/input_mapping_dialog.h', 'nageru/lrameter.h', 'nageru/mainwindow.h', 'nageru/midi_mapping_dialog.h',
-               'nageru/nonlinear_fader.h', 'nageru/vumeter.h'],
+               'nageru/nonlinear_fader.h', 'nageru/vumeter.h', 'nageru/rgb_histogram.h'],
        ui_files: ['nageru/analyzer.ui', 'nageru/audio_expanded_view.ui', 'nageru/audio_miniview.ui', 'nageru/display.ui',
                'nageru/input_mapping.ui', 'nageru/mainwindow.ui', 'nageru/midi_mapping.ui'],
        dependencies: qt5deps)
@@ -197,7 +196,7 @@ qt_files = qt5.preprocess(
 # Qt objects.
 nageru_srcs += ['nageru/glwidget.cpp', 'nageru/mainwindow.cpp', 'nageru/vumeter.cpp', 'nageru/lrameter.cpp', 'nageru/compression_reduction_meter.cpp',
        'nageru/correlation_meter.cpp', 'nageru/analyzer.cpp', 'nageru/input_mapping_dialog.cpp', 'nageru/midi_mapping_dialog.cpp',
-       'nageru/nonlinear_fader.cpp', 'nageru/context_menus.cpp', 'nageru/vu_common.cpp', 'nageru/piecewise_interpolator.cpp', 'nageru/midi_mapper.cpp']
+       'nageru/nonlinear_fader.cpp', 'nageru/context_menus.cpp', 'nageru/vu_common.cpp', 'nageru/piecewise_interpolator.cpp', 'nageru/midi_mapper.cpp', 'nageru/rgb_histogram.cpp']
 
 # Auxiliary objects used for nearly everything.
 aux_srcs = ['nageru/flags.cpp']
index f2d3ae699cf8a0d1e12ca4394f23aac2f95e0197..d8197cc7d63b69fe820d5a5687439a86d4c0600d 100644 (file)
 #include "mixer.h"
 #include "ui_analyzer.h"
 
-// QCustomPlot includes qopenglfunctions.h, which #undefs all of the epoxy
-// definitions (ugh) and doesn't put back any others (ugh). Add the ones we
-// need back.
-
-#define glBindBuffer epoxy_glBindBuffer
-#define glBindFramebuffer epoxy_glBindFramebuffer
-#define glBufferData epoxy_glBufferData
-#define glDeleteBuffers epoxy_glDeleteBuffers
-#define glDisable epoxy_glDisable
-#define glGenBuffers epoxy_glGenBuffers
-#define glGetError epoxy_glGetError
-#define glReadPixels epoxy_glReadPixels
-#define glUnmapBuffer epoxy_glUnmapBuffer
-#define glWaitSync epoxy_glWaitSync
-
 using namespace std;
 
 Analyzer::Analyzer()
@@ -70,10 +55,6 @@ Analyzer::Analyzer()
         glGenBuffers(1, &pbo);
         glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pbo);
         glBufferData(GL_PIXEL_PACK_BUFFER_ARB, global_flags.width * global_flags.height * 4, nullptr, GL_STREAM_READ);
-
-       ui->histogram->xAxis->setVisible(true);
-       ui->histogram->yAxis->setVisible(false);
-       ui->histogram->xAxis->setRange(0, 255);
 }
 
 Analyzer::~Analyzer()
@@ -186,38 +167,14 @@ void Analyzer::grab_clicked()
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
        check_error();
 
-       QVector<double> r_vec(256), g_vec(256), b_vec(256), x_vec(256);
-       double max = 0.0;
+       vector<double> r_vec(256), g_vec(256), b_vec(256);
        for (unsigned i = 0; i < 256; ++i) {
-               x_vec[i] = i;
                r_vec[i] = log(r_hist[i] + 1.0);
                g_vec[i] = log(g_hist[i] + 1.0);
                b_vec[i] = log(b_hist[i] + 1.0);
-
-               max = std::max(max, r_vec[i]);
-               max = std::max(max, g_vec[i]);
-               max = std::max(max, b_vec[i]);
        }
 
-       ui->histogram->clearGraphs();
-       ui->histogram->addGraph();
-       ui->histogram->graph(0)->setData(x_vec, r_vec);
-       ui->histogram->graph(0)->setPen(QPen(Qt::red));
-       ui->histogram->graph(0)->setBrush(QBrush(QColor(255, 127, 127, 80)));
-       ui->histogram->addGraph();
-       ui->histogram->graph(1)->setData(x_vec, g_vec);
-       ui->histogram->graph(1)->setPen(QPen(Qt::green));
-       ui->histogram->graph(1)->setBrush(QBrush(QColor(127, 255, 127, 80)));
-       ui->histogram->addGraph();
-       ui->histogram->graph(2)->setData(x_vec, b_vec);
-       ui->histogram->graph(2)->setPen(QPen(Qt::blue));
-       ui->histogram->graph(2)->setBrush(QBrush(QColor(127, 127, 255, 80)));
-
-       ui->histogram->xAxis->setVisible(true);
-       ui->histogram->yAxis->setVisible(false);
-       ui->histogram->xAxis->setRange(0, 255);
-       ui->histogram->yAxis->setRange(0, max);
-       ui->histogram->replot();
+       ui->histogram->set_histograms(std::move(r_vec), std::move(g_vec), std::move(b_vec));
 
        resource_pool->release_2d_texture(fbo_tex);
        check_error();
index 9cf137e0de695dad7a44c214979ee30122563dc0..be467de3d93a79c424acb88ddbc77f9bdc41f043 100644 (file)
        </layout>
       </item>
       <item>
-       <widget class="QCustomPlot" name="histogram" native="true">
+       <widget class="RGBHistogram" name="histogram" native="true">
         <property name="autoFillBackground">
          <bool>false</bool>
         </property>
    <header>glwidget.h</header>
   </customwidget>
   <customwidget>
-   <class>QCustomPlot</class>
+   <class>RGBHistogram</class>
    <extends>QWidget</extends>
-   <header>qcustomplot.h</header>
+   <header>rgb_histogram.h</header>
    <container>1</container>
   </customwidget>
  </customwidgets>
diff --git a/nageru/rgb_histogram.cpp b/nageru/rgb_histogram.cpp
new file mode 100644 (file)
index 0000000..fb1a0ca
--- /dev/null
@@ -0,0 +1,94 @@
+#include "rgb_histogram.h"
+
+#include <QPainter>
+#include <QRect>
+
+class QPaintEvent;
+class QResizeEvent;
+
+using namespace std;
+
+static constexpr int margin_left = 16;
+static constexpr int margin_top = 14;
+static constexpr int margin_right = 14;
+static constexpr int margin_bottom = 25;
+
+RGBHistogram::RGBHistogram(QWidget *parent)
+       : QWidget(parent), red(256, 0.0), green(256, 0.0), blue(256, 0.0)
+{
+}
+
+void RGBHistogram::set_histograms(std::vector<double> red, std::vector<double> green, std::vector<double> blue)
+{
+       assert(red.size() == 256);
+       assert(green.size() == 256);
+       assert(blue.size() == 256);
+       this->red = std::move(red);
+       this->green = std::move(green);
+       this->blue = std::move(blue);
+       repaint();
+}
+
+void RGBHistogram::paintEvent(QPaintEvent *event)
+{
+       QPainter painter(this);
+       painter.fillRect(0, 0, width(), height(), Qt::white);
+       painter.setRenderHints(QPainter::Antialiasing);
+
+       double max = 0.0;
+       for (unsigned i = 0; i < 256; ++i) {
+               max = std::max(max, red[i]);
+               max = std::max(max, green[i]);
+               max = std::max(max, blue[i]);
+       }
+
+       // Draw the graphs. (We'd like to get rid of the bottom line, but that's just cosmetic.)
+       painter.setPen(QPen(Qt::red));
+       painter.setBrush(QBrush(QColor(255, 127, 127, 80)));
+       draw(red, max, Qt::GlobalColor::red, &painter);
+
+       painter.setPen(QPen(Qt::green));
+       painter.setBrush(QBrush(QColor(127, 255, 127, 80)));
+       draw(green, max, Qt::GlobalColor::green, &painter);
+
+       painter.setPen(QPen(Qt::blue));
+       painter.setBrush(QBrush(QColor(127, 127, 255, 80)));
+       draw(blue, max, Qt::GlobalColor::blue, &painter);
+
+       // Draw the tick lines.
+       int w = (width() - 1) - margin_left - margin_right;
+       painter.setPen(QPen(Qt::black));
+       painter.setBrush(QBrush());
+       for (int i = 0; i < 256; i += 10) {
+               int th = (i % 50 == 0) ? 5 : 2;
+               double x = (i / 255.0) * w + margin_left;
+               double y = (height() - 1) - margin_top - margin_bottom;
+               painter.drawLine(QPointF(x, y + margin_top), QPointF(x, y + margin_top - th));
+       }
+
+       // And the axis labels.
+       for (int i = 0; i < 256; i += 50) {
+               char buf[16];
+               snprintf(buf, sizeof(buf), "%d", i);
+
+               double x = (i / 255.0) * w + margin_left;
+               double y = (height() - 1) - margin_top - margin_bottom;
+               painter.drawText(QRectF(x - 20, y + margin_top, 40, margin_bottom), Qt::AlignCenter | Qt::AlignTop, QString(buf));
+       }
+}
+
+void RGBHistogram::draw(const vector<double> &v, double max, Qt::GlobalColor color, QPainter *painter)
+{
+       int w = (width() - 1) - margin_left - margin_right;
+       int h = (height() - 1) - margin_top - margin_bottom;
+
+       QPointF points[258];
+       points[0] = QPointF(margin_left, margin_top + h);
+       for (int i = 0; i < 256; ++i) {
+               double x = (i / 255.0) * w + margin_left;
+               double y = (1.0 - (v[i] / max)) * h + margin_top;
+               points[i + 1] = QPointF(x, y);
+       }
+       points[257] = QPointF(margin_left + w, margin_top + h);
+       painter->drawPolygon(points, 258);
+}
diff --git a/nageru/rgb_histogram.h b/nageru/rgb_histogram.h
new file mode 100644 (file)
index 0000000..9dce2e6
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef RGB_HISTOGRAM_H
+#define RGB_HISTOGRAM_H
+
+#include <math.h>
+#include <QPixmap>
+#include <QWidget>
+#include <QColor>
+
+#include "vu_common.h"
+
+class QObject;
+class QPaintEvent;
+class QResizeEvent;
+
+class RGBHistogram : public QWidget
+{
+       Q_OBJECT
+
+public:
+       RGBHistogram(QWidget *parent);
+       void set_histograms(std::vector<double> red, std::vector<double> green, std::vector<double> blue);
+
+private:
+       void paintEvent(QPaintEvent *event) override;
+       void draw(const std::vector<double> &v, double max, Qt::GlobalColor color, QPainter *painter);
+
+       std::vector<double> red, green, blue;
+};
+
+#endif