improved perfs and event management
This commit is contained in:
1 parent
667ed0c100
commit
bb99be5889
17 files changed
+626
-59
No files matched your search
+39
-5
@@ -13,6 +13,7 @@
|
||||
#include <ctime>
|
||||
|
||||
#include "layout_store.hpp"
|
||||
#include "waveform.hpp"
|
||||
|
||||
namespace udpscope {
|
||||
namespace {
|
||||
@@ -52,25 +53,30 @@ std::string stem_of(const std::string& file, const char* ext) {
|
||||
/// The palette is fixed rather than the plots': this is navigation, and what has to be told apart at
|
||||
/// a glance is one *event* from another, not one signal from another (for which the names are on the
|
||||
/// row above).
|
||||
bool write_preview(const ExportTable& table, const std::string& path, int width = 480, int height = 160) {
|
||||
///
|
||||
/// The height is **per strip**, not for the whole picture: with a fixed total, a six-signal event got
|
||||
/// 26 pixels a signal and an eight-signal one got 20, which is a smear and not a waveform -- the
|
||||
/// picture has to grow with the signal count, and it is the *viewer* that scales it down to a row.
|
||||
bool write_preview(const ExportTable& table, const std::string& path, int width = 480,
|
||||
int strip_h = 44) {
|
||||
if (table.empty() || table.columns.empty()) return false;
|
||||
const std::size_t rows = table.rows();
|
||||
const std::size_t strips = table.columns.size();
|
||||
const int strip_h = std::max(6, height / static_cast<int>(strips));
|
||||
const int total_h = strip_h * static_cast<int>(strips);
|
||||
static const std::uint32_t kPalette[] = {0x4FA3FFu, 0xFF7A4Fu, 0x6EE07Au, 0xE06ED0u,
|
||||
0xFFD24Fu, 0x6FD8E0u, 0xB9A0FFu, 0xE0E0E0u};
|
||||
|
||||
// One byte per pixel per channel, bottom-up (BMP's own order), padded to a 4-byte row.
|
||||
// One byte per pixel per channel, bottom-up and **blue first** -- both are BMP's own order, and
|
||||
// writing RGB here is what made every external viewer show the traces in the wrong colour.
|
||||
const int row_bytes = ((width * 3) + 3) & ~3;
|
||||
std::vector<unsigned char> pixels(std::size_t(row_bytes) * total_h, 0);
|
||||
const auto put = [&](int x, int y, std::uint32_t rgb, double alpha) {
|
||||
if (x < 0 || y < 0 || x >= width || y >= total_h) return;
|
||||
unsigned char* p = &pixels[std::size_t(total_h - 1 - y) * row_bytes + std::size_t(x) * 3];
|
||||
const double a = std::clamp(alpha, 0.0, 1.0);
|
||||
p[0] = static_cast<unsigned char>(p[0] * (1.0 - a) + ((rgb >> 16) & 0xFF) * a);
|
||||
p[0] = static_cast<unsigned char>(p[0] * (1.0 - a) + (rgb & 0xFF) * a);
|
||||
p[1] = static_cast<unsigned char>(p[1] * (1.0 - a) + ((rgb >> 8) & 0xFF) * a);
|
||||
p[2] = static_cast<unsigned char>(p[2] * (1.0 - a) + (rgb & 0xFF) * a);
|
||||
p[2] = static_cast<unsigned char>(p[2] * (1.0 - a) + ((rgb >> 16) & 0xFF) * a);
|
||||
};
|
||||
// The background: a dark field, so the traces read the way they do on screen.
|
||||
for (int y = 0; y < total_h; ++y) {
|
||||
@@ -268,6 +274,34 @@ std::string EventStore::save(const ExportTable& table, const EventRecord& meta,
|
||||
return samples;
|
||||
}
|
||||
|
||||
std::string EventStore::redraw_preview(const EventRecord& record) const {
|
||||
if (dir_.empty() || record.stem.empty() || record.file.empty()) return {};
|
||||
WaveformReader reader;
|
||||
std::string error;
|
||||
if (!reader.open(record.file, &error)) return {};
|
||||
// The whole event in one table, which an event can afford where an export cannot: it is bounded by
|
||||
// the trigger's own pre/post window, so this is seconds of samples and not a session's worth.
|
||||
ExportTable table;
|
||||
table.columns.resize(reader.names().size());
|
||||
for (std::size_t c = 0; c < table.columns.size(); ++c) {
|
||||
table.columns[c].name = reader.names()[c];
|
||||
table.columns[c].values.reserve(reader.rows());
|
||||
}
|
||||
table.time.reserve(reader.rows());
|
||||
std::vector<float> values(reader.names().size(), 0.0f);
|
||||
double t = 0.0;
|
||||
double abs_t = 0.0;
|
||||
while (reader.next(&t, &abs_t, values.data())) {
|
||||
table.time.push_back(t);
|
||||
for (std::size_t c = 0; c < table.columns.size(); ++c) {
|
||||
table.columns[c].values.push_back(values[c]);
|
||||
}
|
||||
}
|
||||
const std::string path = dir_ + "/" + record.stem + ".bmp";
|
||||
if (!write_preview(table, path)) return {};
|
||||
return path;
|
||||
}
|
||||
|
||||
std::vector<EventRecord> EventStore::list() const {
|
||||
std::vector<EventRecord> out;
|
||||
if (dir_.empty()) return out;
|
||||
|
||||
Reference in new issue
Block a user