satdump/src-core/common/image/expression.cpp

95 lines
3 KiB
C++
Raw Normal View History

2025-03-14 14:39:05 +01:00
#include "expression.h"
2025-01-23 10:18:24 +01:00
#include "core/exception.h"
#include "libs/muparser/muParser.h"
2025-01-23 10:49:17 +01:00
#include "common/utils.h"
2025-01-23 21:47:10 +01:00
#include "common/image/meta.h"
2025-01-23 10:18:24 +01:00
namespace image
{
2025-03-14 14:39:05 +01:00
image::Image generate_image_expression(std::vector<ExpressionChannel> channels, std::string expression)
2025-01-23 10:18:24 +01:00
{
if (!channels.size())
throw satdump_exception("No channels provided!");
2025-03-11 22:02:18 +01:00
size_t width = channels[0].img->width();
size_t height = channels[0].img->height();
2025-01-23 10:49:17 +01:00
int depth = channels[0].img->depth();
2025-01-23 10:18:24 +01:00
try
{
mu::Parser equParser;
2025-03-14 14:39:05 +01:00
equParser.SetExpr(expression);
2025-01-23 10:18:24 +01:00
2025-01-23 21:47:10 +01:00
nlohmann::json proj_cfg;
2025-01-23 10:18:24 +01:00
for (auto &p : channels)
{
2025-01-23 10:49:17 +01:00
if (p.img->width() != width || p.img->height() != height)
2025-01-23 10:18:24 +01:00
throw satdump_exception("All channels must have the same width!");
2025-01-23 10:49:17 +01:00
if (p.img->channels() == 1)
2025-01-23 10:18:24 +01:00
{
equParser.DefineVar(p.tkt, &p.val[0]);
}
else
{
2025-01-23 10:49:17 +01:00
auto tkts = splitString(p.tkt, ',');
for (int i = 0; i < p.img->channels(); i++)
2025-03-11 22:02:18 +01:00
equParser.DefineVar((int)tkts.size() > i ? tkts[i] : (p.tkt + "_" + std::to_string(i + 1)), &p.val[i]);
2025-01-23 10:18:24 +01:00
}
2025-01-23 10:49:17 +01:00
if (p.img->depth() > depth)
depth = p.img->depth();
2025-01-23 21:47:10 +01:00
if (image::has_metadata_proj_cfg(*p.img))
proj_cfg = image::get_metadata_proj_cfg(*p.img);
2025-01-23 10:18:24 +01:00
}
int nout_channels;
equParser.Eval(nout_channels);
// We can't handle over 4
if (nout_channels > 4)
throw satdump_exception("Can't have more than 4 output channels!");
image::Image out(depth,
2025-01-23 10:49:17 +01:00
channels[0].img->width(),
channels[0].img->height(),
2025-01-23 10:18:24 +01:00
nout_channels);
2025-01-23 21:47:10 +01:00
image::set_metadata_proj_cfg(out, proj_cfg);
2025-01-23 10:18:24 +01:00
size_t x, y, c;
for (y = 0; y < height; y++)
{
for (x = 0; x < width; x++)
{
for (auto &p : channels)
{
2025-01-23 10:49:17 +01:00
if (p.img->channels() == 1)
2025-01-23 10:18:24 +01:00
{
2025-01-23 10:49:17 +01:00
p.val[0] = p.img->getf(0, x, y);
2025-01-23 10:18:24 +01:00
}
else
{
2025-01-23 10:49:17 +01:00
for (int i = 0; i < p.img->channels(); i++)
p.val[i] = p.img->getf(i, x, y);
2025-01-23 10:18:24 +01:00
}
}
// Run the parser
double *equOut = equParser.Eval(nout_channels);
// Set output
2025-03-11 22:02:18 +01:00
for (c = 0; c < (size_t)nout_channels; c++)
2025-01-23 10:18:24 +01:00
out.setf(c, x, y, out.clampf(equOut[c]));
}
}
return out;
}
catch (mu::ParserError &e)
{
throw satdump_exception(e.GetMsg());
}
}
}