]> git.sesse.net Git - nageru/blob - nageru/rgb_histogram.cpp
Fix a dangling reference (found by GCC 14).
[nageru] / nageru / rgb_histogram.cpp
1 #include "rgb_histogram.h"
2
3 #include <QBrush>
4 #include <QColor>
5 #include <QPaintDevice>
6 #include <QPainter>
7 #include <QPen>
8 #include <QPoint>
9 #include <QRect>
10 #include <QWidget>
11 #include <algorithm>
12 #include <cassert>
13 #include <cstdio>
14 #include <utility>
15 #include <vector>
16
17 class QPaintEvent;
18 class QResizeEvent;
19
20 using namespace std;
21
22 static constexpr int margin_left = 16;
23 static constexpr int margin_top = 14;
24 static constexpr int margin_right = 14;
25 static constexpr int margin_bottom = 25;
26
27 RGBHistogram::RGBHistogram(QWidget *parent)
28         : QWidget(parent), red(256, 0.0), green(256, 0.0), blue(256, 0.0)
29 {
30 }
31
32 void RGBHistogram::set_histograms(std::vector<double> red, std::vector<double> green, std::vector<double> blue)
33 {
34         assert(red.size() == 256);
35         assert(green.size() == 256);
36         assert(blue.size() == 256);
37         this->red = std::move(red);
38         this->green = std::move(green);
39         this->blue = std::move(blue);
40         repaint();
41 }
42
43 void RGBHistogram::paintEvent(QPaintEvent *event)
44 {
45         QPainter painter(this);
46         painter.fillRect(0, 0, width(), height(), Qt::white);
47         painter.setRenderHints(QPainter::Antialiasing);
48
49         double max = 0.0;
50         for (unsigned i = 0; i < 256; ++i) {
51                 max = std::max(max, red[i]);
52                 max = std::max(max, green[i]);
53                 max = std::max(max, blue[i]);
54         }
55
56         // Draw the graphs. (We'd like to get rid of the bottom line, but that's just cosmetic.)
57         painter.setPen(QPen(Qt::red));
58         painter.setBrush(QBrush(QColor(255, 127, 127, 80)));
59         draw(red, max, Qt::GlobalColor::red, &painter);
60
61         painter.setPen(QPen(Qt::green));
62         painter.setBrush(QBrush(QColor(127, 255, 127, 80)));
63         draw(green, max, Qt::GlobalColor::green, &painter);
64
65         painter.setPen(QPen(Qt::blue));
66         painter.setBrush(QBrush(QColor(127, 127, 255, 80)));
67         draw(blue, max, Qt::GlobalColor::blue, &painter);
68
69         // Draw the tick lines.
70         int w = (width() - 1) - margin_left - margin_right;
71         painter.setPen(QPen(Qt::black));
72         painter.setBrush(QBrush());
73         for (int i = 0; i < 256; i += 10) {
74                 int th = (i % 50 == 0) ? 5 : 2;
75                 double x = (i / 255.0) * w + margin_left;
76                 double y = (height() - 1) - margin_top - margin_bottom;
77                 painter.drawLine(QPointF(x, y + margin_top), QPointF(x, y + margin_top - th));
78         }
79
80         // And the axis labels.
81         for (int i = 0; i < 256; i += 50) {
82                 char buf[16];
83                 snprintf(buf, sizeof(buf), "%d", i);
84
85                 double x = (i / 255.0) * w + margin_left;
86                 double y = (height() - 1) - margin_top - margin_bottom;
87                 painter.drawText(QRectF(x - 20, y + margin_top, 40, margin_bottom), Qt::AlignCenter | Qt::AlignTop, QString(buf));
88         }
89 }
90
91 void RGBHistogram::draw(const vector<double> &v, double max, Qt::GlobalColor color, QPainter *painter)
92 {
93         int w = (width() - 1) - margin_left - margin_right;
94         int h = (height() - 1) - margin_top - margin_bottom;
95
96         QPointF points[258];
97         points[0] = QPointF(margin_left, margin_top + h);
98         for (int i = 0; i < 256; ++i) {
99                 double x = (i / 255.0) * w + margin_left;
100                 double y = (1.0 - (v[i] / max)) * h + margin_top;
101                 points[i + 1] = QPointF(x, y);
102         }
103         points[257] = QPointF(margin_left + w, margin_top + h);
104         painter->drawPolygon(points, 258);
105 }