satdump/src-interface/viewer2/handler/image/image_handler.cpp

258 lines
10 KiB
C++
Raw Normal View History

2025-01-01 16:16:02 +01:00
#include "image_handler.h"
#include "imgui/imgui_stdlib.h"
#include "core/style.h"
2025-01-02 17:04:32 +01:00
#include "common/image/io.h" // TODOREWORK
#include "common/image/processing.h"
2025-01-02 19:07:13 +01:00
#include "nlohmann/json_utils.h"
// TODOREWORK
#include "common/projection/reprojector.h"
2025-01-07 19:07:51 +01:00
#include "common/widgets/json_editor.h"
// TODOREWORK
2025-01-09 13:35:23 +01:00
#include "common/projection/projs2/proj_json.h"
2025-01-07 19:07:51 +01:00
#include "common/projection/warp/warp.h"
#include "common/projection/warp/warp_bkd.h"
2025-01-09 13:35:23 +01:00
#include "projection/raytrace/gcp_compute.h"
2025-01-07 19:07:51 +01:00
#include "common/projection/gcp_compute/gcp_compute.h"
2025-01-01 16:16:02 +01:00
namespace satdump
{
namespace viewer
{
ImageHandler::ImageHandler()
{
}
ImageHandler::~ImageHandler()
{
}
void ImageHandler::drawMenu()
{
2025-01-02 17:04:32 +01:00
bool needs_to_be_disabled = is_processing;
2025-01-01 16:16:02 +01:00
if (ImGui::CollapsingHeader("Image"))
{
2025-01-02 17:04:32 +01:00
bool needs_to_update = false;
if (needs_to_be_disabled)
style::beginDisabled();
needs_to_update |= ImGui::Checkbox("Equalize", &equalize_img);
needs_to_update |= ImGui::Checkbox("Individual Equalize", &equalize_perchannel_img);
needs_to_update |= ImGui::Checkbox("White Balance", &white_balance_img);
needs_to_update |= ImGui::Checkbox("Normalize", &normalize_img);
needs_to_update |= ImGui::Checkbox("Median Blur", &median_blur_img);
2025-01-05 19:57:26 +01:00
needs_to_update |= ImGui::Checkbox("Rotate 180", &rotate180_image);
2025-01-02 17:04:32 +01:00
2025-01-07 19:07:51 +01:00
ImGui::Separator();
needs_to_update |= ImGui::Checkbox("Warp Image", &warp_image);
2025-01-09 13:35:23 +01:00
needs_to_update |= ImGui::Checkbox("Old GCP Math", &old_gcp_math);
2025-01-07 19:07:51 +01:00
if (image_overlay_valib)
2025-01-07 19:07:51 +01:00
{
ImGui::Separator();
needs_to_update |= overlay_handler.drawUI(); // TODOREWORK
2025-01-07 19:07:51 +01:00
needs_to_update |= ImGui::Checkbox("Rotate 180", &rotate180_image);
auto proj_json = image::get_metadata_proj_cfg(image);
widgets::JSONTreeEditor(proj_json, "ProjCfg");
image::set_metadata_proj_cfg(image, proj_json);
}
2025-01-02 17:04:32 +01:00
if (needs_to_be_disabled)
style::endDisabled();
2025-01-03 16:26:39 +01:00
if (image_calib_valid)
{
ImGui::Text("Calibration Unit %s", image_calib.unit.c_str());
ImGui::Text("Calibration Min %f", image_calib.min);
ImGui::Text("Calibration Max %f", image_calib.max);
}
2025-01-02 17:04:32 +01:00
if (needs_to_update)
asyncProcess();
}
if (imgview_needs_update)
{
image_view.update(get_current_img());
imgview_needs_update = false;
2025-01-03 16:26:39 +01:00
image_view.mouseCallback = [this](int x, int y)
{
auto &img = get_current_img();
ImGui::BeginTooltip(); // TODOREWORK
additionalMouseCallback(x, y);
ImGui::Text("Raw : %d", img.get(0, x, y));
if (image_calib_valid && image.channels() == 1)
{
double val = image_calib.getVal(img.getf(0, x, y));
ImGui::Text("Unit : %f %s", val, image_calib.unit.c_str());
}
ImGui::EndTooltip();
};
2025-01-02 17:04:32 +01:00
}
}
void ImageHandler::drawMenuBar()
{
if (ImGui::MenuItem("Save Image"))
{
logger->warn("Saving image to /tmp/out.png!");
image::save_img(get_current_img(), "/tmp/out.png");
2025-01-01 16:16:02 +01:00
}
}
void ImageHandler::drawContents(ImVec2 win_size)
{
image_view.draw(win_size);
}
2025-01-02 17:04:32 +01:00
2025-01-02 19:07:13 +01:00
void ImageHandler::setConfig(nlohmann::json p)
{
2025-01-02 21:30:41 +01:00
equalize_img = getValueOrDefault(p["equalize"], false);
2025-01-02 22:37:59 +01:00
equalize_perchannel_img = getValueOrDefault(p["individual_equalize"], false);
2025-01-02 21:30:41 +01:00
white_balance_img = getValueOrDefault(p["white_balance"], false);
normalize_img = getValueOrDefault(p["normalize"], false);
median_blur_img = getValueOrDefault(p["median_blur"], false);
2025-01-05 19:57:26 +01:00
rotate180_image = getValueOrDefault(p["rotate180_image"], false);
2025-01-02 19:07:13 +01:00
}
nlohmann::json ImageHandler::getConfig()
{
nlohmann::json p;
p["equalize"] = equalize_img;
2025-01-02 22:37:59 +01:00
p["individual_equalize"] = equalize_perchannel_img;
2025-01-02 19:07:13 +01:00
p["white_balance"] = white_balance_img;
p["normalize"] = normalize_img;
p["median_blur"] = median_blur_img;
2025-01-05 19:57:26 +01:00
p["rotate180_image"] = rotate180_image;
2025-01-02 19:07:13 +01:00
return p;
}
2025-01-03 16:26:39 +01:00
void ImageHandler::updateImage(image::Image &img) // TODOREWORK
{
image = img;
2025-01-07 19:07:51 +01:00
image_proj_valid = image_overlay_valib = image::has_metadata_proj_cfg(image); // TODOREWORK
2025-01-03 16:26:39 +01:00
process();
}
2025-01-02 17:04:32 +01:00
void ImageHandler::do_process()
{
bool image_needs_processing = equalize_img |
equalize_perchannel_img |
white_balance_img |
normalize_img |
2025-01-05 19:57:26 +01:00
median_blur_img |
rotate180_image |
2025-01-07 19:07:51 +01:00
overlay_handler.enabled() |
warp_image;
2025-01-02 17:04:32 +01:00
if (image_needs_processing)
{
curr_image = image;
if (equalize_img)
image::equalize(curr_image, false);
if (equalize_perchannel_img)
image::equalize(curr_image, true);
if (white_balance_img)
image::white_balance(curr_image);
if (normalize_img)
image::normalize(curr_image);
if (median_blur_img)
image::median_blur(curr_image);
2025-01-05 19:57:26 +01:00
if (rotate180_image)
curr_image.mirror(true, true);
2025-01-07 19:07:51 +01:00
if (image_proj_valid && warp_image)
{
2025-01-15 17:43:58 +01:00
curr_image = curr_image.to16bits();
2025-01-07 19:07:51 +01:00
auto prj_cfg = image::get_metadata_proj_cfg(image);
warp::WarpOperation operation;
2025-01-09 13:35:23 +01:00
prj_cfg["width"] = image.width(); // TODOREWORK move to metadata already?
prj_cfg["height"] = image.height(); // TODOREWORK move to metadata already?
operation.ground_control_points = old_gcp_math ? satdump::gcp_compute::compute_gcps(prj_cfg) : satdump::proj::compute_gcps(prj_cfg); // img.width(), img.height());
2025-01-07 19:07:51 +01:00
operation.input_image = &curr_image;
operation.output_rgba = true;
// TODO : CHANGE!!!!!!
int l_width = prj_cfg.contains("f_width") ? prj_cfg["f_width"].get<int>() : std::max<int>(image.width(), 512) * 10;
operation.output_width = l_width;
operation.output_height = l_width / 2;
logger->trace("Warping size %dx%d", l_width, l_width / 2);
#if 1
satdump::warp::WarpResult result = satdump::warp::performSmartWarp(operation);
#else
warp::ImageWarper wrapper;
wrapper.op = operation;
wrapper.update();
satdump::warp::WarpResult result = wrapper.warp();
#endif
2025-01-09 13:35:23 +01:00
auto src_proj = ::proj::projection_t();
src_proj.type = ::proj::ProjType_Equirectangular;
2025-01-07 19:07:51 +01:00
src_proj.proj_offset_x = result.top_left.lon;
src_proj.proj_offset_y = result.top_left.lat;
src_proj.proj_scalar_x = (result.bottom_right.lon - result.top_left.lon) / double(result.output_image.width());
src_proj.proj_scalar_y = (result.bottom_right.lat - result.top_left.lat) / double(result.output_image.height());
image::set_metadata_proj_cfg(result.output_image, src_proj);
curr_image = result.output_image;
}
if (image_overlay_valib && overlay_handler.enabled())
{
2025-01-09 13:35:23 +01:00
// auto pfunc = reprojection::setupProjectionFunction(curr_image.width(), curr_image.height(), image::get_metadata_proj_cfg(curr_image), rotate180_image);
auto cfg = image::get_metadata_proj_cfg(curr_image);
cfg["width"] = curr_image.width();
cfg["height"] = curr_image.height();
proj::Projection p = cfg;
p.init(1, 0);
bool rotate = rotate180_image;
auto pfunc = [p, rotate](double lat, double lon, double h, double w) mutable -> std::pair<double, double>
{
double x, y;
if (p.forward(geodetic::geodetic_coords_t(lat, lon, 0, false), x, y) || x < 0 || x >= w || y < 0 || y >= h)
return {-1, -1};
else
{
if (rotate)
return {w - 1 - x, h - 1 - y};
else
return {x, y};
}
};
2025-01-07 19:07:51 +01:00
overlay_handler.clear_cache();
overlay_handler.apply(curr_image, pfunc);
}
2025-01-02 17:04:32 +01:00
}
else
curr_image.clear();
has_second_image = image_needs_processing;
imgview_needs_update = true;
2025-01-03 16:26:39 +01:00
auto &im = get_current_img();
if (image::has_metadata_proj_cfg(im))
{
2025-01-07 19:07:51 +01:00
// logger->critical(image::get_metadata_proj_cfg(im).dump(4));
2025-01-03 16:26:39 +01:00
}
image_calib_valid = false;
if (image::has_metadata_calib_cfg(im))
{
image_calib = image::get_metadata_calib_cfg(im);
image_calib_valid = true;
}
2025-01-02 17:04:32 +01:00
}
2025-01-01 16:16:02 +01:00
}
}