2022-04-12 20:18:44 +02:00
|
|
|
#include "image_handler.h"
|
2022-04-12 21:37:36 +02:00
|
|
|
#include "common/calibration.h"
|
2024-04-24 21:51:02 -04:00
|
|
|
#include "common/image/image_background.h"
|
2022-04-12 21:37:36 +02:00
|
|
|
|
2023-09-25 23:36:38 -04:00
|
|
|
#include "imgui/pfd/pfd_utils.h"
|
2022-04-16 08:10:25 +02:00
|
|
|
#include "imgui/imgui_internal.h"
|
|
|
|
|
|
2022-05-12 14:18:26 +02:00
|
|
|
#include "common/projection/gcp_compute/gcp_compute.h"
|
|
|
|
|
#include "common/projection/warp/warp.h"
|
|
|
|
|
#include "common/projection/projs/equirectangular.h"
|
|
|
|
|
#include "common/map/map_drawer.h"
|
|
|
|
|
#include "resources.h"
|
2022-09-08 20:08:49 +02:00
|
|
|
#include "core/opencl.h"
|
2023-01-22 01:54:24 +01:00
|
|
|
#include "common/widgets/switch.h"
|
2023-10-20 23:33:32 -04:00
|
|
|
#include "common/widgets/stepped_slider.h"
|
2023-10-19 15:42:54 -04:00
|
|
|
#include "main_ui.h"
|
2024-04-26 17:44:12 +02:00
|
|
|
#include "common/image/brightness_contrast.h"
|
2023-09-24 09:14:16 -04:00
|
|
|
|
2024-05-09 16:43:43 +02:00
|
|
|
#include "common/image/meta.h"
|
2024-02-26 12:55:42 +01:00
|
|
|
#include "common/projection/reprojector.h"
|
|
|
|
|
|
2024-05-09 16:43:43 +02:00
|
|
|
#include "common/image/processing.h"
|
2024-05-09 01:16:08 +02:00
|
|
|
#include "common/image/image_lut.h"
|
2024-05-08 17:28:11 +02:00
|
|
|
|
2022-04-12 20:18:44 +02:00
|
|
|
namespace satdump
|
|
|
|
|
{
|
|
|
|
|
void ImageViewerHandler::init()
|
|
|
|
|
{
|
|
|
|
|
products = (ImageProducts *)ViewerHandler::products;
|
|
|
|
|
|
2022-12-31 17:03:29 +01:00
|
|
|
if (products->has_calibation())
|
|
|
|
|
products->init_calibration();
|
|
|
|
|
|
2022-04-12 20:18:44 +02:00
|
|
|
// TMP
|
2022-04-12 21:37:36 +02:00
|
|
|
if (instrument_cfg.contains("rgb_composites"))
|
2023-11-27 15:38:55 +01:00
|
|
|
{
|
2022-04-12 21:37:36 +02:00
|
|
|
for (nlohmann::detail::iteration_proxy_value<nlohmann::detail::iter_impl<nlohmann::ordered_json>> compo : instrument_cfg["rgb_composites"].items())
|
2023-11-27 15:38:55 +01:00
|
|
|
{
|
|
|
|
|
if (check_composite_from_product_can_be_made(*products, compo.value().get<ImageCompositeCfg>()))
|
|
|
|
|
rgb_presets.push_back({compo.key(), compo.value().get<ImageCompositeCfg>()});
|
|
|
|
|
else
|
|
|
|
|
logger->debug("Disabling " + compo.key() + " as it can't be made!");
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-04-12 20:18:44 +02:00
|
|
|
|
|
|
|
|
select_image_str += std::string("Composite") + '\0';
|
|
|
|
|
|
2022-05-12 18:19:01 +02:00
|
|
|
for (int i = 0; i < (int)products->images.size(); i++)
|
2022-04-12 20:18:44 +02:00
|
|
|
{
|
2024-04-29 20:57:33 -04:00
|
|
|
auto &img = products->images[i];
|
2022-04-20 15:57:17 +02:00
|
|
|
select_image_str += "Channel " + img.channel_name + '\0';
|
|
|
|
|
channel_numbers.push_back(img.channel_name);
|
2024-05-07 22:12:33 -04:00
|
|
|
radiance_ranges.push_back(products->get_calibration_default_radiance_range(i));
|
2024-09-17 17:45:32 +02:00
|
|
|
temp_ranges.push_back({radiance_to_temperature(radiance_ranges[i].first, products->get_wavenumber(i)),
|
|
|
|
|
radiance_to_temperature(radiance_ranges[i].second, products->get_wavenumber(i))});
|
2022-04-12 20:18:44 +02:00
|
|
|
}
|
|
|
|
|
|
2023-01-22 18:21:08 +01:00
|
|
|
// generate scale iamge
|
2023-07-05 23:25:38 +02:00
|
|
|
updateScaleImage();
|
|
|
|
|
|
|
|
|
|
// Setup correction factors.
|
|
|
|
|
updateCorrectionFactors(true);
|
|
|
|
|
|
2024-05-09 11:48:39 +02:00
|
|
|
lut_image = image::LUT_jet<uint8_t>();
|
2022-04-12 20:18:44 +02:00
|
|
|
asyncUpdate();
|
2022-09-08 20:08:49 +02:00
|
|
|
|
2023-11-01 18:10:00 +01:00
|
|
|
try
|
|
|
|
|
{
|
2023-11-10 18:13:06 +01:00
|
|
|
overlay_handler.set_config(config::main_cfg["user"]["viewer_state"]["products_handler"][products->instrument_name]["overlay_cfg"], false);
|
2023-11-01 18:10:00 +01:00
|
|
|
}
|
2023-11-25 10:27:43 -05:00
|
|
|
catch (std::exception &)
|
2023-11-01 18:10:00 +01:00
|
|
|
{
|
|
|
|
|
}
|
2022-04-12 20:18:44 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-22 14:52:06 -04:00
|
|
|
ImageViewerHandler::~ImageViewerHandler()
|
|
|
|
|
{
|
|
|
|
|
handler_thread_pool.stop();
|
|
|
|
|
for (int i = 0; i < handler_thread_pool.size(); i++)
|
|
|
|
|
{
|
|
|
|
|
if (handler_thread_pool.get_thread(i).joinable())
|
|
|
|
|
handler_thread_pool.get_thread(i).join();
|
|
|
|
|
}
|
2023-11-01 18:10:00 +01:00
|
|
|
|
2023-11-10 18:13:06 +01:00
|
|
|
config::main_cfg["user"]["viewer_state"]["products_handler"][products->instrument_name]["overlay_cfg"] = overlay_handler.get_config();
|
2023-11-01 18:10:00 +01:00
|
|
|
config::saveUserConfig();
|
2024-09-08 17:08:52 -04:00
|
|
|
delete[] scale_buffer;
|
2023-10-22 14:52:06 -04:00
|
|
|
}
|
|
|
|
|
|
2022-04-12 20:18:44 +02:00
|
|
|
void ImageViewerHandler::updateImage()
|
|
|
|
|
{
|
|
|
|
|
if (select_image_id == 0)
|
2022-12-15 21:43:39 +01:00
|
|
|
{
|
2022-04-12 20:18:44 +02:00
|
|
|
current_image = rgb_image;
|
2022-12-15 21:43:39 +01:00
|
|
|
}
|
2022-09-09 13:13:10 +02:00
|
|
|
else if (select_image_id - 1 < (int)products->images.size())
|
2022-12-15 21:43:39 +01:00
|
|
|
{
|
2023-01-22 16:00:56 +01:00
|
|
|
if (active_channel_calibrated && products->has_calibation())
|
|
|
|
|
{
|
2024-09-17 17:45:32 +02:00
|
|
|
if (products->get_calibration_type(active_channel_id) && is_temp)
|
2024-05-07 22:12:33 -04:00
|
|
|
current_image = products->get_calibrated_image(select_image_id - 1, &rgb_progress,
|
2024-09-17 17:45:32 +02:00
|
|
|
ImageProducts::CALIB_VTYPE_TEMPERATURE, temp_ranges[select_image_id - 1]);
|
2024-05-07 22:12:33 -04:00
|
|
|
else
|
|
|
|
|
current_image = products->get_calibrated_image(select_image_id - 1, &rgb_progress,
|
2024-09-17 17:45:32 +02:00
|
|
|
ImageProducts::CALIB_VTYPE_AUTO, radiance_ranges[select_image_id - 1]);
|
2023-01-22 01:54:24 +01:00
|
|
|
update_needed = false;
|
|
|
|
|
}
|
2023-01-02 01:06:49 +01:00
|
|
|
else
|
|
|
|
|
current_image = products->images[select_image_id - 1].image;
|
2022-12-15 21:43:39 +01:00
|
|
|
current_proj_metadata = products->get_channel_proj_metdata(select_image_id - 1);
|
|
|
|
|
}
|
2022-04-12 20:18:44 +02:00
|
|
|
|
2022-09-05 22:30:53 +02:00
|
|
|
if (select_image_id != 0)
|
|
|
|
|
current_timestamps = products->get_timestamps(select_image_id - 1);
|
|
|
|
|
|
2022-04-27 14:31:36 +02:00
|
|
|
if (median_blur)
|
2024-05-09 01:16:08 +02:00
|
|
|
image::median_blur(current_image);
|
2022-04-27 14:31:36 +02:00
|
|
|
|
2023-11-09 23:58:15 -05:00
|
|
|
if (despeckle)
|
2024-05-08 21:58:51 -04:00
|
|
|
image::kuwahara_filter(current_image);
|
2023-11-09 23:58:15 -05:00
|
|
|
|
2022-04-12 20:18:44 +02:00
|
|
|
if (rotate_image)
|
|
|
|
|
current_image.mirror(true, true);
|
|
|
|
|
|
|
|
|
|
if (equalize_image)
|
2024-05-09 01:16:08 +02:00
|
|
|
image::equalize(current_image);
|
2022-04-12 20:18:44 +02:00
|
|
|
|
2023-09-04 18:00:34 +02:00
|
|
|
if (individual_equalize_image)
|
2024-05-09 01:16:08 +02:00
|
|
|
image::equalize(current_image, true);
|
2023-09-04 18:00:34 +02:00
|
|
|
|
2022-04-13 13:40:44 +02:00
|
|
|
if (white_balance_image)
|
2024-05-09 01:16:08 +02:00
|
|
|
image::white_balance(current_image);
|
2022-04-13 13:40:44 +02:00
|
|
|
|
2022-04-12 20:18:44 +02:00
|
|
|
if (invert_image)
|
2024-05-09 01:16:08 +02:00
|
|
|
image::linear_invert(current_image);
|
2022-04-12 20:18:44 +02:00
|
|
|
|
2022-04-12 21:37:36 +02:00
|
|
|
if (normalize_image)
|
2024-05-09 01:16:08 +02:00
|
|
|
image::normalize(current_image);
|
2022-04-12 21:37:36 +02:00
|
|
|
|
2024-04-26 17:44:12 +02:00
|
|
|
if (manual_brightness_contrast)
|
2024-05-09 01:16:08 +02:00
|
|
|
image::brightness_contrast(current_image, manual_brightness_contrast_brightness, manual_brightness_contrast_constrast);
|
2024-04-26 17:44:12 +02:00
|
|
|
|
2023-08-21 22:02:29 +02:00
|
|
|
// TODO : Cleanup?
|
|
|
|
|
if (using_lut)
|
|
|
|
|
{
|
2023-11-07 11:14:35 +01:00
|
|
|
if (current_image.channels() < 3)
|
|
|
|
|
current_image.to_rgb();
|
2024-05-09 11:57:48 +02:00
|
|
|
if (current_image.depth() != lut_image.depth())
|
2024-05-09 12:34:06 +02:00
|
|
|
current_image = current_image.to_depth(lut_image.depth());
|
2023-08-21 22:02:29 +02:00
|
|
|
for (size_t i = 0; i < current_image.width() * current_image.height(); i++)
|
|
|
|
|
{
|
2024-05-11 15:03:30 -04:00
|
|
|
size_t val = current_image.getf(i) * lut_image.width();
|
2023-08-21 22:02:29 +02:00
|
|
|
if (val >= lut_image.width())
|
|
|
|
|
val = lut_image.width() - 1;
|
2024-05-09 01:16:08 +02:00
|
|
|
current_image.set(0, i, lut_image.get(0, val));
|
|
|
|
|
current_image.set(1, i, lut_image.get(1, val));
|
|
|
|
|
current_image.set(2, i, lut_image.get(2, val));
|
2023-08-21 22:02:29 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-24 21:51:02 -04:00
|
|
|
if (remove_background)
|
|
|
|
|
image::remove_background(current_image, products->get_proj_cfg(), &rgb_progress);
|
|
|
|
|
|
2022-12-16 20:43:47 +01:00
|
|
|
int pre_corrected_width = current_image.width();
|
|
|
|
|
int pre_corrected_height = current_image.height();
|
|
|
|
|
|
2022-09-17 15:04:30 +02:00
|
|
|
std::vector<float> corrected_stuff;
|
|
|
|
|
if (correct_image)
|
|
|
|
|
{
|
|
|
|
|
corrected_stuff.resize(current_image.width());
|
|
|
|
|
bool success = false;
|
2024-05-09 01:16:08 +02:00
|
|
|
image::Image cor = perform_geometric_correction(*products, current_image, success, corrected_stuff.data());
|
2022-09-17 15:04:30 +02:00
|
|
|
if (success)
|
|
|
|
|
current_image = cor;
|
|
|
|
|
if (!success)
|
|
|
|
|
corrected_stuff.clear();
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-01 18:10:00 +01:00
|
|
|
if (overlay_handler.enabled())
|
2022-09-05 22:30:53 +02:00
|
|
|
{
|
2023-12-07 14:08:15 -05:00
|
|
|
// Ensure this is RGB!!
|
2024-01-22 23:03:51 +01:00
|
|
|
if (current_image.channels() < 3)
|
2023-12-07 14:08:15 -05:00
|
|
|
current_image.to_rgb();
|
2023-09-29 23:21:43 +02:00
|
|
|
nlohmann::json proj_cfg = products->get_proj_cfg();
|
|
|
|
|
proj_cfg["metadata"] = current_proj_metadata;
|
2023-09-29 23:50:23 +02:00
|
|
|
if (products->has_tle())
|
|
|
|
|
proj_cfg["metadata"]["tle"] = products->get_tle();
|
2023-09-30 09:35:44 +02:00
|
|
|
if (products->has_timestamps)
|
2023-09-29 23:50:23 +02:00
|
|
|
proj_cfg["metadata"]["timestamps"] = current_timestamps;
|
2022-09-17 15:04:30 +02:00
|
|
|
|
2024-01-03 22:53:32 -05:00
|
|
|
bool do_correction = corrected_stuff.size() != 0 && correct_image;
|
|
|
|
|
if (do_correction != last_correct_image || rotate_image != last_rotate_image ||
|
2024-01-09 16:29:18 -05:00
|
|
|
current_image.width() != last_width || current_image.height() != last_height || last_proj_cfg != proj_cfg)
|
2022-09-17 15:04:30 +02:00
|
|
|
{
|
2024-01-02 17:06:14 -05:00
|
|
|
overlay_handler.clear_cache();
|
|
|
|
|
proj_func = satdump::reprojection::setupProjectionFunction(pre_corrected_width,
|
2024-01-22 23:03:51 +01:00
|
|
|
pre_corrected_height,
|
|
|
|
|
proj_cfg,
|
|
|
|
|
!do_correction && rotate_image);
|
2022-09-17 17:59:02 +02:00
|
|
|
|
2024-01-03 22:53:32 -05:00
|
|
|
if (do_correction)
|
2022-09-17 15:04:30 +02:00
|
|
|
{
|
2024-01-02 17:06:14 -05:00
|
|
|
int fwidth = current_image.width();
|
|
|
|
|
int fheight = current_image.height();
|
|
|
|
|
bool rotate = rotate_image;
|
|
|
|
|
auto &proj_func = this->proj_func;
|
|
|
|
|
|
2024-02-24 22:38:54 +01:00
|
|
|
std::function<std::pair<int, int>(double, double, int, int)> newfun =
|
|
|
|
|
[proj_func, corrected_stuff, fwidth, fheight, rotate](double lat, double lon, int map_height, int map_width) mutable -> std::pair<int, int>
|
2024-01-22 23:03:51 +01:00
|
|
|
{
|
|
|
|
|
std::pair<int, int> ret = proj_func(lat, lon, map_height, map_width);
|
|
|
|
|
if (ret.first != -1 && ret.second != -1 && ret.first < (int)corrected_stuff.size() && ret.first >= 0)
|
2022-09-17 17:59:02 +02:00
|
|
|
{
|
2024-01-22 23:03:51 +01:00
|
|
|
ret.first = corrected_stuff[ret.first];
|
|
|
|
|
if (rotate)
|
2024-01-02 17:06:14 -05:00
|
|
|
{
|
2024-01-22 23:03:51 +01:00
|
|
|
ret.first = (fwidth - 1) - ret.first;
|
|
|
|
|
ret.second = (fheight - 1) - ret.second;
|
2024-01-02 17:06:14 -05:00
|
|
|
}
|
2024-01-22 23:03:51 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
ret.second = ret.first = -1;
|
|
|
|
|
return ret;
|
|
|
|
|
};
|
2024-01-02 17:06:14 -05:00
|
|
|
proj_func = newfun;
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-03 22:53:32 -05:00
|
|
|
last_correct_image = do_correction;
|
2024-01-02 17:06:14 -05:00
|
|
|
last_rotate_image = rotate_image;
|
2024-01-03 22:53:32 -05:00
|
|
|
last_width = current_image.width();
|
|
|
|
|
last_height = current_image.height();
|
2024-01-09 16:29:18 -05:00
|
|
|
last_proj_cfg = proj_cfg;
|
2022-09-17 15:04:30 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-01 18:10:00 +01:00
|
|
|
overlay_handler.apply(current_image, proj_func);
|
2022-09-05 22:30:53 +02:00
|
|
|
}
|
|
|
|
|
|
2022-04-12 20:18:44 +02:00
|
|
|
image_view.update(current_image);
|
|
|
|
|
|
|
|
|
|
// Tooltip function
|
|
|
|
|
image_view.mouseCallback = [this](int x, int y)
|
|
|
|
|
{
|
2022-04-13 17:51:30 +02:00
|
|
|
if (active_channel_id >= 0)
|
2022-04-12 22:34:36 +02:00
|
|
|
{
|
2024-09-19 16:43:42 +02:00
|
|
|
y+=1;
|
2022-04-13 17:51:30 +02:00
|
|
|
if (rotate_image)
|
|
|
|
|
{
|
|
|
|
|
x = current_image.width() - 1 - x;
|
|
|
|
|
y = current_image.height() - 1 - y;
|
|
|
|
|
}
|
2022-04-12 21:37:36 +02:00
|
|
|
|
2024-05-08 14:52:24 +02:00
|
|
|
int raw_value = products->images[active_channel_id].image.get(0, correct_image ? correction_factors[x] : x, y) >> (products->images[active_channel_id].image.depth() - products->bit_depth);
|
2022-04-12 21:37:36 +02:00
|
|
|
|
2022-04-13 13:40:44 +02:00
|
|
|
ImGui::BeginTooltip();
|
|
|
|
|
ImGui::Text("Count : %d", raw_value);
|
2023-11-23 22:53:47 +01:00
|
|
|
if (products->has_calibation() && products->get_wavenumber(active_channel_id) != -1)
|
2022-04-12 22:34:36 +02:00
|
|
|
{
|
2023-01-02 19:35:29 +01:00
|
|
|
double radiance = products->get_calibrated_value(active_channel_id, x, y);
|
2023-01-31 02:37:41 +01:00
|
|
|
if (correct_image)
|
|
|
|
|
{
|
2023-07-05 23:25:38 +02:00
|
|
|
updateCorrectionFactors();
|
2023-01-28 21:46:16 +01:00
|
|
|
radiance = products->get_calibrated_value(active_channel_id, correction_factors[x], y);
|
|
|
|
|
}
|
2023-11-05 16:54:28 +01:00
|
|
|
if (radiance != CALIBRATION_INVALID_VALUE)
|
2022-12-31 02:18:15 +01:00
|
|
|
{
|
2023-11-05 16:54:28 +01:00
|
|
|
if (products->get_calibration_type(active_channel_id) == products->CALIB_REFLECTANCE)
|
|
|
|
|
{
|
|
|
|
|
ImGui::Text("Albedo : %.2f %%", radiance * 100.0);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ImGui::Text("Radiance : %.10f", radiance);
|
|
|
|
|
ImGui::Text("Temperature : %.2f °C", radiance_to_temperature(radiance, products->get_wavenumber(active_channel_id)) - 273.15);
|
|
|
|
|
}
|
2022-12-31 02:18:15 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2023-11-05 16:54:28 +01:00
|
|
|
ImGui::Text("Calibration Error! - Invalid Value");
|
2022-12-31 02:18:15 +01:00
|
|
|
}
|
2022-04-12 22:34:36 +02:00
|
|
|
}
|
|
|
|
|
ImGui::EndTooltip();
|
|
|
|
|
|
|
|
|
|
/*if (ImGui::IsMouseClicked(ImGuiMouseButton_Left))
|
|
|
|
|
{
|
2023-05-08 23:08:34 +02:00
|
|
|
logger->info("%d, %d", x, y);
|
2022-04-12 22:34:36 +02:00
|
|
|
}*/
|
|
|
|
|
}
|
2022-04-12 20:18:44 +02:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ImageViewerHandler::asyncUpdate()
|
|
|
|
|
{
|
2023-10-22 14:52:06 -04:00
|
|
|
handler_thread_pool.clear_queue();
|
|
|
|
|
handler_thread_pool.push([this](int)
|
2023-11-01 18:10:00 +01:00
|
|
|
{ async_image_mutex.lock();
|
2023-10-16 21:18:01 -04:00
|
|
|
is_updating = true;
|
2022-04-12 20:18:44 +02:00
|
|
|
logger->info("Update image...");
|
|
|
|
|
updateImage();
|
|
|
|
|
logger->info("Done");
|
2023-10-16 21:18:01 -04:00
|
|
|
is_updating = false;
|
2022-04-12 20:18:44 +02:00
|
|
|
async_image_mutex.unlock(); });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ImageViewerHandler::updateRGB()
|
|
|
|
|
{
|
|
|
|
|
rgb_processing = true;
|
2022-04-13 17:51:30 +02:00
|
|
|
active_channel_id = -1;
|
2023-10-22 14:52:06 -04:00
|
|
|
handler_thread_pool.clear_queue();
|
|
|
|
|
handler_thread_pool.push([this](int)
|
2023-11-01 18:10:00 +01:00
|
|
|
{
|
2022-12-12 15:18:43 +01:00
|
|
|
async_image_mutex.lock();
|
2022-04-12 20:18:44 +02:00
|
|
|
logger->info("Generating RGB Composite");
|
2024-09-17 17:45:32 +02:00
|
|
|
satdump::ImageCompositeCfg cfg;
|
2022-04-20 15:57:17 +02:00
|
|
|
cfg.equation = rgb_compo_cfg.equation;
|
2022-06-04 00:48:51 +02:00
|
|
|
cfg.lut = rgb_compo_cfg.lut;
|
2023-01-09 15:13:25 +01:00
|
|
|
cfg.channels = rgb_compo_cfg.channels;
|
|
|
|
|
cfg.lua = rgb_compo_cfg.lua;
|
2024-04-22 12:17:41 +02:00
|
|
|
cfg.cpp = rgb_compo_cfg.cpp;
|
|
|
|
|
cfg.vars = rgb_compo_cfg.vars;
|
2024-09-17 17:45:32 +02:00
|
|
|
cfg.calib_cfg.clear();
|
|
|
|
|
|
1980-01-01 00:00:00 +00:00
|
|
|
if(select_rgb_presets >= 0)
|
2024-09-17 17:45:32 +02:00
|
|
|
{
|
|
|
|
|
// median_blur = rgb_compo_cfg.median_blur;
|
|
|
|
|
// despeckle = rgb_compo_cfg.despeckle;
|
|
|
|
|
equalize_image = rgb_compo_cfg.equalize;
|
|
|
|
|
individual_equalize_image = rgb_compo_cfg.individual_equalize;
|
|
|
|
|
invert_image = rgb_compo_cfg.invert;
|
|
|
|
|
normalize_image = rgb_compo_cfg.normalize;
|
|
|
|
|
white_balance_image = rgb_compo_cfg.white_balance;
|
|
|
|
|
remove_background = rgb_compo_cfg.remove_background;
|
|
|
|
|
using_lut = rgb_compo_cfg.apply_lut;
|
|
|
|
|
|
|
|
|
|
// Test
|
|
|
|
|
cfg.calib_cfg = rgb_compo_cfg.calib_cfg;
|
|
|
|
|
}
|
2022-04-20 15:57:17 +02:00
|
|
|
|
2024-05-08 14:52:24 +02:00
|
|
|
rgb_image = satdump::make_composite_from_product(*products, cfg, &rgb_progress, ¤t_timestamps, ¤t_proj_metadata);
|
2022-04-12 20:18:44 +02:00
|
|
|
select_image_id = 0;
|
|
|
|
|
updateImage();
|
|
|
|
|
logger->info("Done");
|
2022-12-12 15:18:43 +01:00
|
|
|
rgb_processing = false;
|
|
|
|
|
async_image_mutex.unlock(); });
|
2022-04-12 20:18:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ImageViewerHandler::drawMenu()
|
|
|
|
|
{
|
|
|
|
|
if (ImGui::CollapsingHeader("Image"))
|
|
|
|
|
{
|
2022-05-22 17:37:11 +02:00
|
|
|
if (products->images.size() < 100)
|
2022-04-13 17:51:30 +02:00
|
|
|
{
|
2022-05-22 17:37:11 +02:00
|
|
|
if (ImGui::Combo("##imagechannelcombo", &select_image_id, select_image_str.c_str()))
|
|
|
|
|
{
|
|
|
|
|
if (select_image_id == 0)
|
|
|
|
|
active_channel_id = -1;
|
|
|
|
|
else
|
|
|
|
|
active_channel_id = select_image_id - 1;
|
|
|
|
|
asyncUpdate();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (ImGui::InputInt("##imagechannelint", &select_image_id))
|
|
|
|
|
{
|
2022-06-28 21:58:52 +00:00
|
|
|
if (select_image_id > (int)products->images.size())
|
|
|
|
|
select_image_id = (int)products->images.size();
|
2022-05-22 17:37:11 +02:00
|
|
|
else if (select_image_id < 0)
|
|
|
|
|
select_image_id = 0;
|
|
|
|
|
|
|
|
|
|
if (select_image_id == 0)
|
|
|
|
|
active_channel_id = -1;
|
|
|
|
|
else
|
|
|
|
|
active_channel_id = select_image_id - 1;
|
|
|
|
|
asyncUpdate();
|
|
|
|
|
}
|
2022-04-13 17:51:30 +02:00
|
|
|
}
|
2022-04-12 20:18:44 +02:00
|
|
|
|
2023-01-22 01:54:24 +01:00
|
|
|
if (ImGui::IsItemHovered() && active_channel_id >= 0)
|
2022-04-13 13:40:44 +02:00
|
|
|
{
|
2023-11-23 22:53:47 +01:00
|
|
|
if (products->get_wavenumber(active_channel_id) != -1)
|
2022-04-13 13:40:44 +02:00
|
|
|
{
|
2023-01-22 01:54:24 +01:00
|
|
|
ImGui::BeginTooltip();
|
2024-09-26 22:51:25 -04:00
|
|
|
ImGui::Text(u8"Wavenumber : %f cm\u207b\u00b9", products->get_wavenumber(active_channel_id));
|
2022-04-13 17:51:30 +02:00
|
|
|
double wl_nm = 1e7 / products->get_wavenumber(active_channel_id);
|
2022-04-13 13:40:44 +02:00
|
|
|
double frequency = 299792458.0 / (wl_nm * 10e-10);
|
|
|
|
|
|
|
|
|
|
if (wl_nm < 1e3)
|
|
|
|
|
ImGui::Text("Wavelength : %f nm", wl_nm);
|
|
|
|
|
else if (wl_nm < 1e6)
|
2024-09-18 22:38:54 +02:00
|
|
|
ImGui::Text("Wavelength : %f µm", wl_nm / 1e3);
|
2022-04-13 13:40:44 +02:00
|
|
|
else if (wl_nm < 1e9)
|
|
|
|
|
ImGui::Text("Wavelength : %f mm", wl_nm / 1e6);
|
|
|
|
|
else
|
|
|
|
|
ImGui::Text("Wavelength : %f cm", wl_nm / 1e7);
|
|
|
|
|
|
|
|
|
|
if (frequency < 1e3)
|
|
|
|
|
ImGui::Text("Frequency : %f Hz", frequency);
|
|
|
|
|
else if (frequency < 1e6)
|
|
|
|
|
ImGui::Text("Frequency : %f kHz", frequency / 1e3);
|
|
|
|
|
else if (frequency < 1e9)
|
|
|
|
|
ImGui::Text("Frequency : %f MHz", frequency / 1e6);
|
|
|
|
|
else
|
|
|
|
|
ImGui::Text("Frequency : %f GHz", frequency / 1e9);
|
2023-01-22 01:54:24 +01:00
|
|
|
ImGui::EndTooltip();
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-01-22 20:44:44 +01:00
|
|
|
|
2023-11-23 22:53:47 +01:00
|
|
|
if (products->has_calibation() && active_channel_id >= 0 && products->get_wavenumber(active_channel_id) != -1)
|
2023-01-22 01:54:24 +01:00
|
|
|
{
|
2024-09-08 22:25:10 -04:00
|
|
|
ImGuiStyle &imgui_style = ImGui::GetStyle();
|
2024-01-21 14:17:18 -05:00
|
|
|
int to_pop = 0;
|
2023-01-22 16:00:56 +01:00
|
|
|
ImGui::SameLine();
|
2023-01-22 18:21:08 +01:00
|
|
|
if (range_window && active_channel_calibrated)
|
2023-01-22 16:00:56 +01:00
|
|
|
{
|
2024-09-08 22:25:10 -04:00
|
|
|
ImGui::PushStyleColor(ImGuiCol_Button, imgui_style.Colors[ImGuiCol_TabActive]);
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, imgui_style.Colors[ImGuiCol_TabHovered]);
|
2024-01-21 14:17:18 -05:00
|
|
|
to_pop += 2;
|
2022-04-13 13:40:44 +02:00
|
|
|
}
|
2023-01-22 16:00:56 +01:00
|
|
|
if (!active_channel_calibrated)
|
|
|
|
|
ImGui::BeginDisabled();
|
|
|
|
|
if (ImGui::Button(u8"\uf07e"))
|
|
|
|
|
range_window = !range_window;
|
2023-01-22 18:21:08 +01:00
|
|
|
if (ImGui::IsItemHovered())
|
|
|
|
|
ImGui::SetTooltip("Diaplay Range Control");
|
2024-01-21 14:17:18 -05:00
|
|
|
ImGui::PopStyleColor(to_pop);
|
|
|
|
|
to_pop = 0;
|
2023-01-22 18:21:08 +01:00
|
|
|
|
|
|
|
|
if (show_scale && active_channel_calibrated)
|
|
|
|
|
{
|
2024-09-08 22:25:10 -04:00
|
|
|
ImGui::PushStyleColor(ImGuiCol_Button, imgui_style.Colors[ImGuiCol_TabActive]);
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, imgui_style.Colors[ImGuiCol_TabHovered]);
|
2024-01-21 14:17:18 -05:00
|
|
|
to_pop += 2;
|
2023-01-22 18:21:08 +01:00
|
|
|
}
|
|
|
|
|
if (!products->get_calibration_type(active_channel_id))
|
|
|
|
|
ImGui::BeginDisabled();
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button(u8"\uf2c9"))
|
|
|
|
|
show_scale = !show_scale;
|
|
|
|
|
if (!products->get_calibration_type(active_channel_id))
|
|
|
|
|
ImGui::EndDisabled();
|
2024-01-21 14:17:18 -05:00
|
|
|
ImGui::PopStyleColor(to_pop);
|
|
|
|
|
to_pop = 0;
|
2023-01-22 18:21:08 +01:00
|
|
|
|
2023-01-22 16:00:56 +01:00
|
|
|
if (!active_channel_calibrated)
|
|
|
|
|
ImGui::EndDisabled();
|
2022-04-13 13:40:44 +02:00
|
|
|
|
2023-01-22 16:00:56 +01:00
|
|
|
if (ImGui::IsItemHovered())
|
2023-01-22 18:21:08 +01:00
|
|
|
ImGui::SetTooltip("Show Scale");
|
2023-01-22 01:54:24 +01:00
|
|
|
|
2023-01-22 18:21:08 +01:00
|
|
|
if (range_window && active_channel_calibrated)
|
2023-01-22 16:00:56 +01:00
|
|
|
{
|
|
|
|
|
ImGui::Begin("Display Range Control", &range_window, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize);
|
|
|
|
|
ImGui::SetWindowSize(ImVec2(200 * ui_scale, 115 * ui_scale));
|
|
|
|
|
bool buff = false;
|
2024-09-17 17:45:32 +02:00
|
|
|
std::pair<double, double> &this_range = products->get_calibration_type(active_channel_id) && is_temp ? temp_ranges[active_channel_id] : radiance_ranges[active_channel_id];
|
2024-05-07 22:12:33 -04:00
|
|
|
double tmp_min = (this_range.first * (products->get_calibration_type(active_channel_id) ? 1 : 100));
|
|
|
|
|
double tmp_max = (this_range.second * (products->get_calibration_type(active_channel_id) ? 1 : 100));
|
2024-09-26 21:26:04 -04:00
|
|
|
|
|
|
|
|
std::string format_string;
|
|
|
|
|
if (is_temp && products->get_calibration_type(active_channel_id))
|
|
|
|
|
format_string = "%.1f K";
|
|
|
|
|
else if (products->get_calibration_type(active_channel_id))
|
|
|
|
|
format_string = u8"%.2f W\u00B7sr\u207b\u00b9\u00B7m\u207b\u00b2";
|
|
|
|
|
else
|
|
|
|
|
format_string = "%.2f%% Albedo";
|
|
|
|
|
|
2023-01-22 16:00:56 +01:00
|
|
|
ImGui::SetNextItemWidth(120 * ui_scale);
|
2024-09-26 21:26:04 -04:00
|
|
|
buff |= ImGui::InputDouble("Minimum", &tmp_min, 0, 0, format_string.c_str(), ImGuiInputTextFlags_EnterReturnsTrue);
|
2023-01-22 16:00:56 +01:00
|
|
|
ImGui::SetNextItemWidth(120 * ui_scale);
|
2024-09-26 21:26:04 -04:00
|
|
|
buff |= ImGui::InputDouble("Maximum", &tmp_max, 0, 0, format_string.c_str(), ImGuiInputTextFlags_EnterReturnsTrue);
|
2023-01-22 16:00:56 +01:00
|
|
|
if (buff)
|
|
|
|
|
{
|
2024-05-07 22:12:33 -04:00
|
|
|
this_range.first = (tmp_min / (products->get_calibration_type(active_channel_id) ? 1 : 100));
|
|
|
|
|
this_range.second = (tmp_max / (products->get_calibration_type(active_channel_id) ? 1 : 100));
|
2023-01-22 16:00:56 +01:00
|
|
|
update_needed = true;
|
|
|
|
|
asyncUpdate();
|
|
|
|
|
}
|
|
|
|
|
if (ImGui::Button("Default"))
|
|
|
|
|
{
|
2024-09-17 17:45:32 +02:00
|
|
|
this_range = is_temp && products->get_calibration_type(active_channel_id) ? std::pair<double, double>{radiance_to_temperature(products->get_calibration_default_radiance_range(active_channel_id).first, products->get_wavenumber(active_channel_id)),
|
|
|
|
|
radiance_to_temperature(products->get_calibration_default_radiance_range(active_channel_id).second, products->get_wavenumber(active_channel_id))}
|
|
|
|
|
: products->get_calibration_default_radiance_range(active_channel_id);
|
2023-01-22 16:00:56 +01:00
|
|
|
update_needed = true;
|
|
|
|
|
asyncUpdate();
|
|
|
|
|
}
|
|
|
|
|
ImGui::End();
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-22 18:21:08 +01:00
|
|
|
if (show_scale && active_channel_calibrated && products->get_calibration_type(active_channel_id))
|
|
|
|
|
{
|
2024-09-17 17:45:32 +02:00
|
|
|
if (scale_has_update)
|
2024-09-25 23:52:27 -04:00
|
|
|
{
|
|
|
|
|
if(scale_texture_id == 0)
|
|
|
|
|
scale_texture_id = makeImageTexture();
|
2024-09-08 17:08:52 -04:00
|
|
|
updateImageTexture(scale_texture_id, scale_buffer, 25, 512);
|
2024-09-25 23:52:27 -04:00
|
|
|
scale_has_update = false;
|
|
|
|
|
}
|
2024-09-08 17:08:52 -04:00
|
|
|
|
2023-01-22 18:21:08 +01:00
|
|
|
int w = ImGui::GetWindowSize()[0];
|
2024-09-17 17:45:32 +02:00
|
|
|
if (ImGui::Begin("Scale##scale_window", &show_scale, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize))
|
2023-01-22 20:44:44 +01:00
|
|
|
{
|
2024-09-08 17:08:52 -04:00
|
|
|
ImGui::SetWindowSize(ImVec2(100 * ui_scale, 520 * ui_scale));
|
|
|
|
|
ImGui::SetWindowPos(ImVec2(w + 20 * ui_scale, 50 * ui_scale), ImGuiCond_Once);
|
|
|
|
|
|
|
|
|
|
ImDrawList *draw_list = ImGui::GetWindowDrawList();
|
|
|
|
|
float num_height = ImGui::CalcTextSize("0").y;
|
|
|
|
|
float scale_height = (460 * ui_scale) - num_height;
|
|
|
|
|
float start_y = ImGui::GetCursorPosY();
|
|
|
|
|
float graduation_start_y = ImGui::GetCursorScreenPos().y + (num_height / 2);
|
|
|
|
|
float graduation_start_x = ImGui::GetCursorScreenPos().x + (22 * ui_scale);
|
2024-09-08 22:25:10 -04:00
|
|
|
float graduation_length = imgui_style.ItemSpacing.x * 0.75f;
|
2024-09-08 17:08:52 -04:00
|
|
|
|
|
|
|
|
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + num_height / 2);
|
|
|
|
|
ImGui::Image((void *)(intptr_t)scale_texture_id, ImVec2(22 * ui_scale, scale_height));
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
ImGui::SetCursorPosY(start_y);
|
|
|
|
|
ImGui::BeginGroup();
|
|
|
|
|
|
|
|
|
|
std::pair<double, double> actual_ranges = is_temp ? temp_ranges[active_channel_id] : radiance_ranges[active_channel_id];
|
|
|
|
|
float step_difference = std::abs(actual_ranges.first - actual_ranges.second) / 9;
|
|
|
|
|
float step_height = (scale_height - 1) / 9;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 10; i++)
|
|
|
|
|
{
|
|
|
|
|
ImGui::SetCursorPosY(start_y + i * step_height);
|
2024-09-08 17:20:16 -04:00
|
|
|
ImGui::Text("%.3f", actual_ranges.second - i * step_difference);
|
2024-09-08 17:08:52 -04:00
|
|
|
draw_list->AddLine(ImVec2(graduation_start_x, graduation_start_y + i * step_height),
|
2024-09-17 17:45:32 +02:00
|
|
|
ImVec2(graduation_start_x + graduation_length, graduation_start_y + i * step_height),
|
|
|
|
|
ImGui::ColorConvertFloat4ToU32(imgui_style.Colors[ImGuiCol_TextDisabled]), 1.0 * ui_scale);
|
2024-09-08 17:08:52 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImGui::EndGroup();
|
2024-10-15 21:59:48 -04:00
|
|
|
ImGui::Text(is_temp ? u8" [K]" : u8" [W\u00b7sr\u207b\u00b9\u00b7m\u207b\u00b2]");
|
2023-01-22 18:21:08 +01:00
|
|
|
}
|
|
|
|
|
ImGui::End();
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-22 16:00:56 +01:00
|
|
|
ImGui::Spacing();
|
|
|
|
|
|
|
|
|
|
ImGui::BeginGroup();
|
|
|
|
|
if (products->get_calibration_type(active_channel_id))
|
2023-01-22 18:21:08 +01:00
|
|
|
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 3 * ui_scale);
|
2023-01-22 16:00:56 +01:00
|
|
|
ImGui::Text("Raw Counts");
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
|
|
|
|
|
ImGui::SetNextItemWidth(50);
|
|
|
|
|
ToggleButton("##caltog", (int *)&active_channel_calibrated);
|
|
|
|
|
if (ImGui::IsItemClicked())
|
|
|
|
|
asyncUpdate();
|
|
|
|
|
ImGui::SameLine();
|
2023-01-22 18:21:08 +01:00
|
|
|
if (products->get_calibration_type(active_channel_id))
|
|
|
|
|
{
|
|
|
|
|
ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 3 * ui_scale);
|
2023-01-22 16:00:56 +01:00
|
|
|
ImGui::SetNextItemWidth(90 * ui_scale);
|
2023-01-22 18:21:08 +01:00
|
|
|
// ImGui::Combo("##temp_rad", &tst, "Radiance\0Temperature");
|
|
|
|
|
if (ImGui::BeginCombo("##temp_rad", is_temp ? "Temperature" : "Radiance", ImGuiComboFlags_NoArrowButton))
|
|
|
|
|
{
|
|
|
|
|
if (ImGui::Selectable("Radiance", !is_temp))
|
|
|
|
|
{
|
2023-01-22 16:00:56 +01:00
|
|
|
is_temp = false;
|
2024-05-07 22:12:33 -04:00
|
|
|
asyncUpdate();
|
2023-01-22 16:00:56 +01:00
|
|
|
}
|
2023-01-22 18:21:08 +01:00
|
|
|
if (!is_temp)
|
2023-01-22 16:00:56 +01:00
|
|
|
ImGui::SetItemDefaultFocus();
|
|
|
|
|
|
2023-01-22 18:21:08 +01:00
|
|
|
if (ImGui::Selectable("Temperature", is_temp))
|
|
|
|
|
{
|
2023-01-22 16:00:56 +01:00
|
|
|
is_temp = true;
|
2024-05-07 22:12:33 -04:00
|
|
|
asyncUpdate();
|
2023-01-22 16:00:56 +01:00
|
|
|
}
|
2023-01-22 18:21:08 +01:00
|
|
|
if (is_temp)
|
2023-01-22 16:00:56 +01:00
|
|
|
ImGui::SetItemDefaultFocus();
|
|
|
|
|
ImGui::EndCombo();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
ImGui::Text("Albedo");
|
|
|
|
|
ImGui::EndGroup();
|
|
|
|
|
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
ImGui::Separator();
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
}
|
2023-01-22 01:54:24 +01:00
|
|
|
|
2022-04-27 14:31:36 +02:00
|
|
|
if (ImGui::Checkbox("Median Blur", &median_blur))
|
|
|
|
|
asyncUpdate();
|
|
|
|
|
|
2023-11-09 23:58:15 -05:00
|
|
|
if (ImGui::Checkbox("Despeckle", &despeckle))
|
|
|
|
|
asyncUpdate();
|
|
|
|
|
|
2022-04-12 20:18:44 +02:00
|
|
|
if (ImGui::Checkbox("Rotate", &rotate_image))
|
|
|
|
|
asyncUpdate();
|
|
|
|
|
|
2024-04-24 21:51:02 -04:00
|
|
|
if (products->can_geometrically_correct() && ImGui::Checkbox("Correct", &correct_image))
|
|
|
|
|
asyncUpdate();
|
|
|
|
|
|
|
|
|
|
if (products->can_remove_background() && ImGui::Checkbox("Remove Background", &remove_background))
|
|
|
|
|
asyncUpdate();
|
2022-07-22 20:14:30 +02:00
|
|
|
|
2022-04-12 20:18:44 +02:00
|
|
|
if (ImGui::Checkbox("Equalize", &equalize_image))
|
|
|
|
|
asyncUpdate();
|
|
|
|
|
|
2023-09-04 18:00:34 +02:00
|
|
|
if (ImGui::Checkbox("Individual Equalize", &individual_equalize_image))
|
|
|
|
|
asyncUpdate();
|
|
|
|
|
|
2022-04-13 13:40:44 +02:00
|
|
|
if (ImGui::Checkbox("White Balance", &white_balance_image))
|
|
|
|
|
asyncUpdate();
|
|
|
|
|
|
2022-04-12 21:37:36 +02:00
|
|
|
if (ImGui::Checkbox("Normalize", &normalize_image))
|
|
|
|
|
asyncUpdate();
|
|
|
|
|
|
2023-05-20 19:19:44 +02:00
|
|
|
if (ImGui::Checkbox("Invert", &invert_image))
|
|
|
|
|
{
|
2023-07-05 23:25:38 +02:00
|
|
|
updateScaleImage();
|
2022-04-12 20:18:44 +02:00
|
|
|
asyncUpdate();
|
2023-02-02 23:11:48 +01:00
|
|
|
}
|
2022-04-12 20:18:44 +02:00
|
|
|
|
2023-07-05 23:25:38 +02:00
|
|
|
if (ImGui::Checkbox("Apply LUT##lutoption", &using_lut))
|
|
|
|
|
{
|
|
|
|
|
asyncUpdate();
|
|
|
|
|
updateScaleImage();
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-26 17:44:12 +02:00
|
|
|
if (ImGui::Checkbox("Manual Brightness/Constrast", &manual_brightness_contrast))
|
|
|
|
|
asyncUpdate();
|
|
|
|
|
if (manual_brightness_contrast)
|
|
|
|
|
{
|
|
|
|
|
if (ImGui::SliderFloat("Brightness", &manual_brightness_contrast_brightness, -2, 2))
|
|
|
|
|
asyncUpdate();
|
|
|
|
|
if (ImGui::SliderFloat("Contrast", &manual_brightness_contrast_constrast, -2, 2))
|
|
|
|
|
asyncUpdate();
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-16 21:18:01 -04:00
|
|
|
bool save_disabled = is_updating || rgb_processing;
|
2023-11-01 18:10:00 +01:00
|
|
|
if (save_disabled)
|
2023-10-16 21:18:01 -04:00
|
|
|
style::beginDisabled();
|
2022-04-12 20:18:44 +02:00
|
|
|
if (ImGui::Button("Save"))
|
|
|
|
|
{
|
2023-10-22 14:52:06 -04:00
|
|
|
handler_thread_pool.clear_queue();
|
2024-09-17 17:45:32 +02:00
|
|
|
handler_thread_pool.push([this](int)
|
|
|
|
|
{
|
2024-10-09 09:13:38 -04:00
|
|
|
async_image_mutex.lock();
|
|
|
|
|
is_updating = true;
|
|
|
|
|
logger->info("Saving Image...");
|
|
|
|
|
std::string default_path = config::main_cfg["satdump_directories"]["default_image_output_directory"]["value"].get<std::string>();
|
|
|
|
|
std::string saved_at = save_image_dialog(products->instrument_name + "_" +
|
|
|
|
|
(select_image_id == 0 ? "composite" : ("ch" + channel_numbers[select_image_id - 1])),
|
|
|
|
|
default_path, "Save Image", ¤t_image, &viewer_app->save_type);
|
|
|
|
|
|
|
|
|
|
if (saved_at == "")
|
|
|
|
|
logger->info("Save cancelled");
|
|
|
|
|
else
|
|
|
|
|
logger->info("Saved current image at %s", saved_at.c_str());
|
|
|
|
|
is_updating = false;
|
|
|
|
|
async_image_mutex.unlock(); });
|
2022-04-12 20:18:44 +02:00
|
|
|
}
|
2023-10-16 21:18:01 -04:00
|
|
|
if (save_disabled)
|
|
|
|
|
{
|
|
|
|
|
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
|
|
|
|
|
ImGui::SetTooltip("Updating, please wait...");
|
|
|
|
|
style::endDisabled();
|
|
|
|
|
}
|
2022-04-12 20:18:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ImGui::CollapsingHeader("RGB Composites"))
|
|
|
|
|
{
|
2023-11-17 09:37:51 -05:00
|
|
|
bool show_info_button = select_rgb_presets != -1 && rgb_compo_cfg.description_markdown != "";
|
2023-11-25 10:27:43 -05:00
|
|
|
if (ImGui::BeginCombo(show_info_button ? "##presetcombo" : "Preset##presetcombo",
|
2023-11-27 15:38:55 +01:00
|
|
|
select_rgb_presets == -1 ? "" : rgb_presets[select_rgb_presets].first.c_str()))
|
2022-04-12 20:18:44 +02:00
|
|
|
{
|
2023-11-25 10:54:02 -05:00
|
|
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
2023-11-25 10:27:43 -05:00
|
|
|
ImGui::InputTextWithHint("##searchpresets", u8"\uf422 Search", &preset_search_str);
|
|
|
|
|
for (size_t i = 0; i < rgb_presets.size(); i++)
|
|
|
|
|
{
|
|
|
|
|
bool show = true;
|
|
|
|
|
if (preset_search_str.size() != 0)
|
|
|
|
|
show = isStringPresent(rgb_presets[i].first, preset_search_str);
|
|
|
|
|
|
2024-01-22 23:03:51 +01:00
|
|
|
if (show && ImGui::Selectable(rgb_presets[i].first.c_str(), (int)i == select_rgb_presets))
|
2023-11-25 10:27:43 -05:00
|
|
|
{
|
|
|
|
|
select_rgb_presets = i;
|
|
|
|
|
rgb_compo_cfg = rgb_presets[select_rgb_presets].second;
|
|
|
|
|
updateRGB();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ImGui::EndCombo();
|
2022-04-12 20:18:44 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-17 09:37:51 -05:00
|
|
|
if (show_info_button)
|
2023-11-14 21:31:59 +01:00
|
|
|
{
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
|
2023-11-25 10:27:43 -05:00
|
|
|
if (ImGui::Button(u8"\uf449 Info###compopresetinfo"))
|
2023-11-14 21:31:59 +01:00
|
|
|
{
|
|
|
|
|
std::ifstream ifs(resources::getResourcePath(rgb_compo_cfg.description_markdown));
|
|
|
|
|
std::string desc_markdown((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
|
|
|
|
|
markdown_composite_info.set_md(desc_markdown);
|
|
|
|
|
show_markdown_description = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-21 22:02:29 +02:00
|
|
|
if (ImGui::InputText("##rgbEquation", &rgb_compo_cfg.equation))
|
2023-10-04 00:48:56 +02:00
|
|
|
{
|
2023-08-21 22:02:29 +02:00
|
|
|
select_rgb_presets = -1; // Editing, NOT the compo anymore!
|
2024-04-23 22:41:14 +02:00
|
|
|
rgb_compo_cfg.cpp = "";
|
2023-10-04 00:48:56 +02:00
|
|
|
rgb_compo_cfg.lua = "";
|
|
|
|
|
rgb_compo_cfg.lut = "";
|
|
|
|
|
}
|
2022-04-12 20:18:44 +02:00
|
|
|
if (rgb_processing)
|
|
|
|
|
style::beginDisabled();
|
|
|
|
|
if (ImGui::Button("Apply") && !rgb_processing)
|
|
|
|
|
{
|
|
|
|
|
updateRGB();
|
|
|
|
|
return; // Avoid causing ImGui issues!
|
|
|
|
|
}
|
|
|
|
|
if (rgb_processing)
|
|
|
|
|
style::endDisabled();
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
ImGui::ProgressBar(rgb_progress);
|
|
|
|
|
}
|
2022-04-13 13:40:44 +02:00
|
|
|
|
2023-01-17 12:42:28 +01:00
|
|
|
#if 0
|
2022-04-13 13:40:44 +02:00
|
|
|
if (ImGui::CollapsingHeader("Products"))
|
|
|
|
|
{
|
2022-04-13 17:51:30 +02:00
|
|
|
if (products->has_calibation())
|
2022-04-13 13:40:44 +02:00
|
|
|
{
|
2022-04-13 17:51:30 +02:00
|
|
|
if (ImGui::Button("Temperature"))
|
2022-04-13 13:40:44 +02:00
|
|
|
{
|
2022-04-13 17:51:30 +02:00
|
|
|
active_channel_id = select_image_id - 1;
|
|
|
|
|
|
2022-04-20 15:57:17 +02:00
|
|
|
rgb_image = products->images[active_channel_id].image;
|
2022-04-13 17:51:30 +02:00
|
|
|
rgb_image.to_rgb();
|
|
|
|
|
|
2022-04-20 15:57:17 +02:00
|
|
|
for (size_t y = 0; y < products->images[active_channel_id].image.height(); y++)
|
2022-04-13 13:40:44 +02:00
|
|
|
{
|
2022-04-20 15:57:17 +02:00
|
|
|
for (size_t x = 0; x < products->images[active_channel_id].image.width(); x++)
|
2022-04-13 17:51:30 +02:00
|
|
|
{
|
2022-12-31 02:18:15 +01:00
|
|
|
float temp_c = radiance_to_temperature(products->get_calibrated_value(active_channel_id, x, y), products->get_wavenumber(active_channel_id)) - 273.15;
|
2022-04-13 13:40:44 +02:00
|
|
|
|
2022-04-13 17:51:30 +02:00
|
|
|
image::Image<uint16_t> lut = image::LUT_jet<uint16_t>();
|
2022-04-13 13:40:44 +02:00
|
|
|
|
2022-04-13 17:51:30 +02:00
|
|
|
int value = ((temp_c + 10) / 15) * 256;
|
2022-04-13 13:40:44 +02:00
|
|
|
|
2022-04-13 17:51:30 +02:00
|
|
|
if (value < 0)
|
|
|
|
|
value = 0;
|
|
|
|
|
if (value > 255)
|
|
|
|
|
value = 255;
|
2022-04-13 13:40:44 +02:00
|
|
|
|
2022-04-13 17:51:30 +02:00
|
|
|
rgb_image.channel(0)[y * rgb_image.width() + x] = lut.channel(0)[value];
|
|
|
|
|
rgb_image.channel(1)[y * rgb_image.width() + x] = lut.channel(1)[value];
|
|
|
|
|
rgb_image.channel(2)[y * rgb_image.width() + x] = lut.channel(2)[value];
|
|
|
|
|
}
|
2022-04-13 13:40:44 +02:00
|
|
|
}
|
|
|
|
|
|
2022-04-13 17:51:30 +02:00
|
|
|
select_image_id = 0;
|
|
|
|
|
asyncUpdate();
|
|
|
|
|
}
|
2022-04-13 13:40:44 +02:00
|
|
|
}
|
|
|
|
|
}
|
2023-01-17 12:42:28 +01:00
|
|
|
#endif
|
2022-05-12 14:18:26 +02:00
|
|
|
|
2022-09-05 22:30:53 +02:00
|
|
|
if (products->has_proj_cfg())
|
|
|
|
|
{
|
|
|
|
|
if (ImGui::CollapsingHeader("Map Overlay"))
|
|
|
|
|
{
|
2023-11-01 18:10:00 +01:00
|
|
|
if (overlay_handler.drawUI())
|
2023-08-26 16:44:25 +07:00
|
|
|
asyncUpdate();
|
2022-09-05 22:30:53 +02:00
|
|
|
}
|
|
|
|
|
|
2022-09-08 17:24:54 +02:00
|
|
|
if (ImGui::CollapsingHeader("Projection"))
|
2022-05-12 14:18:26 +02:00
|
|
|
{
|
2022-09-08 20:52:57 +02:00
|
|
|
ImGui::BeginGroup();
|
2022-09-08 17:24:54 +02:00
|
|
|
if (!canBeProjected())
|
|
|
|
|
style::beginDisabled();
|
2024-02-26 12:55:42 +01:00
|
|
|
if (ImGui::Button("Add to Projections"))
|
|
|
|
|
addCurrentToProjections();
|
2024-02-28 19:52:09 -05:00
|
|
|
proj_notif.draw();
|
|
|
|
|
ImGui::Checkbox("Old Algorithm", &projection_use_old_algo);
|
2022-09-08 17:24:54 +02:00
|
|
|
if (!canBeProjected())
|
|
|
|
|
style::endDisabled();
|
|
|
|
|
|
2022-09-08 20:52:57 +02:00
|
|
|
ImGui::EndGroup();
|
2024-02-27 22:55:48 +01:00
|
|
|
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled) && !canBeProjected())
|
2022-09-08 20:52:57 +02:00
|
|
|
{
|
|
|
|
|
ImGui::BeginTooltip();
|
2022-09-08 22:03:04 +02:00
|
|
|
if (current_timestamps.size() == 0)
|
2024-01-21 14:57:41 -05:00
|
|
|
ImGui::TextColored(style::theme.red, "No timestamps!");
|
2022-09-08 22:03:04 +02:00
|
|
|
else if (correct_image)
|
2024-01-21 14:57:41 -05:00
|
|
|
ImGui::TextColored(style::theme.red, "Disable correction!");
|
2024-02-28 00:24:04 +01:00
|
|
|
else
|
|
|
|
|
ImGui::TextColored(style::theme.yellow, "The old algorithm will\n"
|
|
|
|
|
"deal with very bad (noisy) data\n"
|
|
|
|
|
"better.\n"
|
|
|
|
|
"The new one is preferred if\n"
|
|
|
|
|
"possible though, as results\n"
|
|
|
|
|
"are a lot nicer! :-)\n"
|
|
|
|
|
"If you had to use this\n"
|
|
|
|
|
"and the data was not that bad\n"
|
|
|
|
|
"please report as a bug!");
|
2023-09-29 22:11:28 +02:00
|
|
|
|
2022-09-08 20:52:57 +02:00
|
|
|
ImGui::EndTooltip();
|
|
|
|
|
}
|
2022-05-12 14:18:26 +02:00
|
|
|
}
|
2022-09-08 17:24:54 +02:00
|
|
|
}
|
2023-11-14 21:31:59 +01:00
|
|
|
|
|
|
|
|
if (show_markdown_description)
|
|
|
|
|
{
|
2023-11-27 15:38:55 +01:00
|
|
|
ImGuiIO &io = ImGui::GetIO();
|
|
|
|
|
ImGui::SetNextWindowSize({400 * ui_scale, 400 * ui_scale}, ImGuiCond_Appearing);
|
2023-11-17 09:19:45 -05:00
|
|
|
ImGui::SetNextWindowPos(ImVec2((io.DisplaySize.x / 2) - (400 * ui_scale / 2), (io.DisplaySize.y / 2) - (400 * ui_scale / 2)), ImGuiCond_Appearing);
|
2023-11-19 21:01:00 -05:00
|
|
|
ImGui::Begin("Composite Info", &show_markdown_description, ImGuiWindowFlags_NoSavedSettings);
|
|
|
|
|
markdown_composite_info.render();
|
2023-11-14 21:31:59 +01:00
|
|
|
ImGui::End();
|
|
|
|
|
}
|
2022-04-12 20:18:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ImageViewerHandler::drawContents(ImVec2 win_size)
|
|
|
|
|
{
|
|
|
|
|
image_view.draw(win_size);
|
|
|
|
|
}
|
2022-04-13 17:51:30 +02:00
|
|
|
|
2022-09-02 01:36:57 +02:00
|
|
|
float ImageViewerHandler::drawTreeMenu()
|
2022-04-16 08:10:25 +02:00
|
|
|
{
|
2022-09-02 01:36:57 +02:00
|
|
|
tree_local.start();
|
2022-04-16 08:10:25 +02:00
|
|
|
|
2022-09-09 23:59:22 +02:00
|
|
|
#if 0
|
2022-09-02 01:36:57 +02:00
|
|
|
for (std::pair<std::string, ImageCompositeCfg> &compo : rgb_presets)
|
2022-04-16 08:10:25 +02:00
|
|
|
{
|
2022-09-02 01:36:57 +02:00
|
|
|
ImGui::TreeNodeEx(std::string("RGB " + compo.first).c_str(), ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen);
|
|
|
|
|
if (ImGui::IsItemClicked())
|
2022-04-16 08:10:25 +02:00
|
|
|
{
|
2022-09-02 01:36:57 +02:00
|
|
|
rgb_compo_cfg = compo.second;
|
|
|
|
|
updateRGB();
|
2022-04-16 08:10:25 +02:00
|
|
|
}
|
2022-09-02 01:36:57 +02:00
|
|
|
tree_local.node();
|
2022-04-13 17:51:30 +02:00
|
|
|
}
|
2022-09-09 23:59:22 +02:00
|
|
|
#endif
|
2022-04-16 08:10:25 +02:00
|
|
|
|
2022-09-02 01:36:57 +02:00
|
|
|
return tree_local.end();
|
2022-04-13 17:51:30 +02:00
|
|
|
}
|
2022-09-07 21:11:44 +02:00
|
|
|
|
2023-07-05 23:25:38 +02:00
|
|
|
void ImageViewerHandler::updateScaleImage()
|
|
|
|
|
{
|
2024-05-09 01:16:08 +02:00
|
|
|
scale_image = image::Image(16, 25, 512, 3);
|
2024-09-08 17:08:52 -04:00
|
|
|
for (size_t i = 0; i < 512; i++)
|
2023-07-05 23:25:38 +02:00
|
|
|
{
|
2024-09-17 17:45:32 +02:00
|
|
|
std::vector<double> color = {double((511 - i) << 7) / 65535.0, double((511 - i) << 7) / 65535.0, double((511 - i) << 7) / 65535.0};
|
2024-09-08 17:08:52 -04:00
|
|
|
if (using_lut)
|
2023-07-05 23:25:38 +02:00
|
|
|
{
|
2024-09-08 17:08:52 -04:00
|
|
|
uint16_t val = color[0] * lut_image.width();
|
|
|
|
|
if (val >= lut_image.width())
|
|
|
|
|
val = lut_image.width() - 1;
|
|
|
|
|
color[0] = lut_image.getf(0, val);
|
|
|
|
|
color[1] = lut_image.getf(1, val);
|
|
|
|
|
color[2] = lut_image.getf(2, val);
|
|
|
|
|
}
|
2023-07-05 23:25:38 +02:00
|
|
|
|
2024-09-08 17:08:52 -04:00
|
|
|
for (int x = 0; x < 25; x++)
|
2023-07-05 23:25:38 +02:00
|
|
|
scale_image.draw_pixel(x, i, color);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (invert_image)
|
|
|
|
|
scale_image.mirror(false, true);
|
|
|
|
|
|
2024-09-25 23:52:27 -04:00
|
|
|
if (scale_buffer == nullptr)
|
2024-09-08 17:08:52 -04:00
|
|
|
scale_buffer = new uint32_t[25 * 512];
|
|
|
|
|
|
|
|
|
|
image::image_to_rgba(scale_image, scale_buffer);
|
|
|
|
|
scale_has_update = true;
|
2023-07-05 23:25:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ImageViewerHandler::updateCorrectionFactors(bool first)
|
|
|
|
|
{
|
|
|
|
|
if (first)
|
|
|
|
|
{
|
|
|
|
|
if (products->images.size() > 0)
|
|
|
|
|
{
|
|
|
|
|
correction_factors = generate_horizontal_corr_lut(*products, products->images[0].image.width());
|
|
|
|
|
correction_factors.push_back(products->images[0].image.width());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (correction_factors[correction_factors.size() - 1] != (int)products->images[active_channel_id].image.width())
|
|
|
|
|
{
|
|
|
|
|
correction_factors = generate_horizontal_corr_lut(*products, products->images[active_channel_id].image.width());
|
|
|
|
|
correction_factors.push_back(products->images[active_channel_id].image.width());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-07 21:11:44 +02:00
|
|
|
bool ImageViewerHandler::canBeProjected()
|
|
|
|
|
{
|
|
|
|
|
return products->has_proj_cfg() &&
|
2023-09-29 23:50:23 +02:00
|
|
|
// products->has_tle() &&
|
|
|
|
|
// products->has_proj_cfg() &&
|
|
|
|
|
// current_timestamps.size() > 0 &&
|
|
|
|
|
// Perhaps we need to check based on the projection type or such?
|
2022-09-07 21:11:44 +02:00
|
|
|
!correct_image;
|
|
|
|
|
}
|
2022-09-07 21:54:04 +02:00
|
|
|
|
2024-02-26 12:55:42 +01:00
|
|
|
void ImageViewerHandler::addCurrentToProjections()
|
2022-09-07 21:54:04 +02:00
|
|
|
{
|
2022-09-07 22:20:48 +02:00
|
|
|
if (canBeProjected())
|
|
|
|
|
{
|
2023-09-29 23:51:10 +02:00
|
|
|
try
|
|
|
|
|
{
|
2024-02-28 16:10:05 -05:00
|
|
|
// Get projection information
|
2024-02-26 12:55:42 +01:00
|
|
|
nlohmann::json proj_cfg;
|
|
|
|
|
proj_cfg = products->get_proj_cfg();
|
|
|
|
|
proj_cfg["metadata"] = current_proj_metadata;
|
2023-09-29 23:51:10 +02:00
|
|
|
if (products->has_tle())
|
2024-02-26 12:55:42 +01:00
|
|
|
proj_cfg["metadata"]["tle"] = products->get_tle();
|
2023-09-30 09:35:44 +02:00
|
|
|
if (products->has_timestamps)
|
2024-02-26 12:55:42 +01:00
|
|
|
proj_cfg["metadata"]["timestamps"] = current_timestamps;
|
2024-02-26 16:18:26 +01:00
|
|
|
image::set_metadata_proj_cfg(current_image, proj_cfg);
|
2024-02-28 16:10:05 -05:00
|
|
|
|
|
|
|
|
// Create projection title
|
2024-03-04 10:57:02 -05:00
|
|
|
std::string timestring, object_name, instrument_name, composite_name;
|
|
|
|
|
if (current_timestamps.size() > 0)
|
|
|
|
|
timestring = "[" + timestamp_to_string(get_median(current_timestamps)) + "] ";
|
|
|
|
|
else
|
|
|
|
|
timestring = "";
|
2024-02-28 16:10:05 -05:00
|
|
|
if (instrument_cfg.contains("name"))
|
2024-03-04 10:57:02 -05:00
|
|
|
instrument_name = instrument_cfg["name"];
|
|
|
|
|
else
|
|
|
|
|
instrument_name = products->instrument_name;
|
|
|
|
|
if (products->has_tle())
|
|
|
|
|
object_name = products->get_tle().name;
|
2024-02-28 16:10:05 -05:00
|
|
|
else
|
2024-03-04 10:57:02 -05:00
|
|
|
object_name = "";
|
|
|
|
|
if (timestring != "" || object_name != "")
|
|
|
|
|
object_name += "\n";
|
2024-02-28 16:10:05 -05:00
|
|
|
if (active_channel_id >= 0)
|
|
|
|
|
composite_name = "Channel " + channel_numbers[active_channel_id];
|
|
|
|
|
else if (select_rgb_presets == -1)
|
|
|
|
|
composite_name = "Custom (" + rgb_compo_cfg.equation + ")";
|
2024-02-28 16:46:33 +01:00
|
|
|
else
|
2024-02-28 16:10:05 -05:00
|
|
|
composite_name = rgb_presets[select_rgb_presets].first;
|
|
|
|
|
|
|
|
|
|
// Add projection layer and settings
|
2024-04-05 23:02:15 -04:00
|
|
|
viewer_app->projection_layers.push_front({timestring + object_name + instrument_name + " - " + composite_name, current_image});
|
2024-02-26 12:55:42 +01:00
|
|
|
|
|
|
|
|
if (rotate_image)
|
2024-04-06 16:11:56 -04:00
|
|
|
viewer_app->projection_layers.front().img.mirror(true, true);
|
2024-02-28 00:24:04 +01:00
|
|
|
if (projection_use_old_algo)
|
2024-04-06 16:11:56 -04:00
|
|
|
viewer_app->projection_layers.front().old_algo = true;
|
2024-02-28 16:46:33 +01:00
|
|
|
|
2024-02-28 17:26:48 +01:00
|
|
|
proj_notif.set_message(style::theme.green, "Added!");
|
2023-09-29 23:51:10 +02:00
|
|
|
}
|
|
|
|
|
catch (std::exception &e)
|
|
|
|
|
{
|
|
|
|
|
logger->error("Could not project image! %s", e.what());
|
|
|
|
|
}
|
2022-09-07 22:20:48 +02:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
logger->error("Current image can't be projected!");
|
|
|
|
|
}
|
2022-09-07 21:54:04 +02:00
|
|
|
}
|
2023-09-26 00:02:27 -04:00
|
|
|
}
|