From 0a9e7553eb17ab06167fc3cab699066c4639683e Mon Sep 17 00:00:00 2001 From: Pascal Thomet Date: Fri, 22 Mar 2024 12:58:03 +0100 Subject: [PATCH] Add json serialization for ImageParams --- CMakeLists.txt | 7 + src/immvision/CMakeLists.txt | 3 + src/immvision/image.h | 5 + .../internal/image_params_serialize.cpp | 184 +++++++++++++++++ src_all_in_one/immvision/immvision.cpp | 193 ++++++++++++++++++ src_all_in_one/immvision/immvision.h | 5 + 6 files changed, 397 insertions(+) create mode 100644 src/immvision/internal/image_params_serialize.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 02f7223..b9a048e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,13 @@ option(IMMVISION_FETCH_OPENCV OFF) option(IMMVISION_FETCH_OPENCV_FULL OFF) #------------------------------------------------------------------------------ +#------------------------------------------------------------------------------ +# IMMVISION_SERIALIZE_JSON +# if ON, the ImageParams class will be able to serialize to JSON +# This requires nlohmann/json +option(IMMVISION_SERIALIZE_JSON OFF) +#------------------------------------------------------------------------------ + #------------------------------------------------------------------------------ # IMMVISION_BUILD_DEMOS diff --git a/src/immvision/CMakeLists.txt b/src/immvision/CMakeLists.txt index c9d87ff..7b5aefa 100644 --- a/src/immvision/CMakeLists.txt +++ b/src/immvision/CMakeLists.txt @@ -3,6 +3,9 @@ find_package(OpenCV REQUIRED) set(target_name immvision) add_library(${target_name} ${sources}) +if (IMMVISION_SERIALIZE_JSON) + target_compile_options(${target_name} PUBLIC -DIMMVISION_SERIALIZE_JSON) +endif() target_include_directories(${target_name} PUBLIC $) target_link_libraries(${target_name} PUBLIC diff --git a/src/immvision/image.h b/src/immvision/image.h index 5ac0e36..c587588 100644 --- a/src/immvision/image.h +++ b/src/immvision/image.h @@ -183,6 +183,11 @@ namespace ImmVision ~ImageParams(); }; +#ifdef IMMVISION_SERIALIZE_JSON + IMMVISION_API std::string ImageParamsToJson(const ImageParams& params); + IMMVISION_API void FillImageParamsFromJson(const std::string& json, ImageParams* params); + IMMVISION_API ImageParams ImageParamsFromJson(const std::string& json); +#endif // Create ImageParams that display the image only, with no decoration, and no user interaction IMMVISION_API ImageParams FactorImageParamsDisplayOnly(); diff --git a/src/immvision/internal/image_params_serialize.cpp b/src/immvision/internal/image_params_serialize.cpp new file mode 100644 index 0000000..58dd0c2 --- /dev/null +++ b/src/immvision/internal/image_params_serialize.cpp @@ -0,0 +1,184 @@ +#ifdef IMMVISION_SERIALIZE_JSON + +#include "immvision/image.h" +#include "nlohmann/json.hpp" + +namespace nlohmann +{ + template <> + struct adl_serializer + { + static void to_json(json& j, const cv::Size& size) { + j = json{{"width", size.width}, {"height", size.height}}; + } + + static void from_json(const json& j, cv::Size& size) { + j.at("width").get_to(size.width); + j.at("height").get_to(size.height); + } + }; + + template <> + struct adl_serializer + { + static void to_json(json& j, const cv::Point& point) { + j = json{{"x", point.x}, {"y", point.y}}; + } + + static void from_json(const json& j, cv::Point& point) { + j.at("x").get_to(point.x); + j.at("y").get_to(point.y); + } + }; + + template <> + struct adl_serializer + { + static void to_json(json& j, const cv::Matx33d& mat) { + for (int row = 0; row < 3; ++row) { + for (int col = 0; col < 3; ++col) { + j[std::to_string(row) + std::to_string(col)] = mat(row, col); + } + } + } + + static void from_json(const json& j, cv::Matx33d& mat) { + for (int row = 0; row < 3; ++row) { + for (int col = 0; col < 3; ++col) { + mat(row, col) = j[std::to_string(row) + std::to_string(col)]; + } + } + } + }; + + template <> + struct adl_serializer + { + static void to_json(json& j, const ImmVision::ColormapScaleFromStatsData& data) { + j = json{ + {"ColorMapStatsType", data.ColorMapStatsType}, + {"NbSigmas", data.NbSigmas}, + {"UseStatsMin", data.UseStatsMin}, + {"UseStatsMax", data.UseStatsMax} + }; + } + + static void from_json(const json& j, ImmVision::ColormapScaleFromStatsData& data) { + j.at("ColorMapStatsType").get_to(data.ColorMapStatsType); + j.at("NbSigmas").get_to(data.NbSigmas); + j.at("UseStatsMin").get_to(data.UseStatsMin); + j.at("UseStatsMax").get_to(data.UseStatsMax); + } + }; + + template <> + struct adl_serializer + { + static void to_json(json& j, const ImmVision::ColormapSettingsData& data) { + j = json{ + {"Colormap", data.Colormap}, + {"ColormapScaleMin", data.ColormapScaleMin}, + {"ColormapScaleMax", data.ColormapScaleMax}, + {"ColormapScaleFromStats", data.ColormapScaleFromStats}, + {"internal_ColormapHovered", data.internal_ColormapHovered} + }; + } + + static void from_json(const json& j, ImmVision::ColormapSettingsData& data) { + j.at("Colormap").get_to(data.Colormap); + j.at("ColormapScaleMin").get_to(data.ColormapScaleMin); + j.at("ColormapScaleMax").get_to(data.ColormapScaleMax); + j.at("ColormapScaleFromStats").get_to(data.ColormapScaleFromStats); + j.at("internal_ColormapHovered").get_to(data.internal_ColormapHovered); + } + }; + + template <> + struct adl_serializer + { + static void to_json(json& j, const ImmVision::ImageParams& params) + { + j = json{ + {"RefreshImage", params.RefreshImage}, + {"ImageDisplaySize", params.ImageDisplaySize}, + {"ZoomPanMatrix", params.ZoomPanMatrix}, + {"ZoomKey", params.ZoomKey}, + {"ColormapSettings", params.ColormapSettings}, + {"ColormapKey", params.ColormapKey}, + {"PanWithMouse", params.PanWithMouse}, + {"ZoomWithMouseWheel", params.ZoomWithMouseWheel}, + {"IsColorOrderBGR", params.IsColorOrderBGR}, + {"SelectedChannel", params.SelectedChannel}, + {"ShowSchoolPaperBackground", params.ShowSchoolPaperBackground}, + {"ShowAlphaChannelCheckerboard", params.ShowAlphaChannelCheckerboard}, + {"ShowGrid", params.ShowGrid}, + {"DrawValuesOnZoomedPixels", params.DrawValuesOnZoomedPixels}, + {"ShowImageInfo", params.ShowImageInfo}, + {"ShowPixelInfo", params.ShowPixelInfo}, + {"ShowZoomButtons", params.ShowZoomButtons}, + {"ShowOptionsPanel", params.ShowOptionsPanel}, + {"ShowOptionsInTooltip", params.ShowOptionsInTooltip}, + {"ShowOptionsButton", params.ShowOptionsButton}, + {"WatchedPixels", params.WatchedPixels}, + {"AddWatchedPixelOnDoubleClick", params.AddWatchedPixelOnDoubleClick}, + {"HighlightWatchedPixels", params.HighlightWatchedPixels} + }; + } + + static void from_json(const json& j, ImmVision::ImageParams& params) + { + j.at("RefreshImage").get_to(params.RefreshImage); + j.at("ImageDisplaySize").get_to(params.ImageDisplaySize); + j.at("ZoomPanMatrix").get_to(params.ZoomPanMatrix); + j.at("ZoomKey").get_to(params.ZoomKey); + j.at("ColormapSettings").get_to(params.ColormapSettings); + j.at("ColormapKey").get_to(params.ColormapKey); + j.at("PanWithMouse").get_to(params.PanWithMouse); + j.at("ZoomWithMouseWheel").get_to(params.ZoomWithMouseWheel); + j.at("IsColorOrderBGR").get_to(params.IsColorOrderBGR); + j.at("SelectedChannel").get_to(params.SelectedChannel); + j.at("ShowSchoolPaperBackground").get_to(params.ShowSchoolPaperBackground); + j.at("ShowAlphaChannelCheckerboard").get_to(params.ShowAlphaChannelCheckerboard); + j.at("ShowGrid").get_to(params.ShowGrid); + j.at("DrawValuesOnZoomedPixels").get_to(params.DrawValuesOnZoomedPixels); + j.at("ShowImageInfo").get_to(params.ShowImageInfo); + j.at("ShowPixelInfo").get_to(params.ShowPixelInfo); + j.at("ShowZoomButtons").get_to(params.ShowZoomButtons); + j.at("ShowOptionsPanel").get_to(params.ShowOptionsPanel); + j.at("ShowOptionsInTooltip").get_to(params.ShowOptionsInTooltip); + j.at("ShowOptionsButton").get_to(params.ShowOptionsButton); + j.at("WatchedPixels").get_to(params.WatchedPixels); + j.at("AddWatchedPixelOnDoubleClick").get_to(params.AddWatchedPixelOnDoubleClick); + j.at("HighlightWatchedPixels").get_to(params.HighlightWatchedPixels); + } + + }; +} // namespace nlohmann + + +namespace ImmVision +{ + using json = nlohmann::json; + + + std::string ImageParamsToJson(const ImageParams& params) + { + json j = params; + return j.dump(4); + } + + void FillImageParamsFromJson(const std::string& json, ImageParams* params) + { + nlohmann::json j = nlohmann::json::parse(json); + nlohmann::adl_serializer::from_json(j, *params); + } + + ImageParams ImageParamsFromJson(const std::string& json) + { + ImageParams params; + FillImageParamsFromJson(json, ¶ms); + return params; + } + +} +#endif diff --git a/src_all_in_one/immvision/immvision.cpp b/src_all_in_one/immvision/immvision.cpp index 0745dfd..89db521 100644 --- a/src_all_in_one/immvision/immvision.cpp +++ b/src_all_in_one/immvision/immvision.cpp @@ -196,6 +196,11 @@ namespace ImmVision ~ImageParams(); }; +#ifdef IMMVISION_SERIALIZE_JSON + IMMVISION_API std::string ImageParamsToJson(const ImageParams& params); + IMMVISION_API void FillImageParamsFromJson(const std::string& json, ImageParams* params); + IMMVISION_API ImageParams ImageParamsFromJson(const std::string& json); +#endif // Create ImageParams that display the image only, with no decoration, and no user interaction IMMVISION_API ImageParams FactorImageParamsDisplayOnly(); @@ -10323,6 +10328,194 @@ namespace ImmVision } // namespace ImmVision +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// src/immvision/internal/image_params_serialize.cpp // +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#ifdef IMMVISION_SERIALIZE_JSON + +#include "nlohmann/json.hpp" + +namespace nlohmann +{ + template <> + struct adl_serializer + { + static void to_json(json& j, const cv::Size& size) { + j = json{{"width", size.width}, {"height", size.height}}; + } + + static void from_json(const json& j, cv::Size& size) { + j.at("width").get_to(size.width); + j.at("height").get_to(size.height); + } + }; + + template <> + struct adl_serializer + { + static void to_json(json& j, const cv::Point& point) { + j = json{{"x", point.x}, {"y", point.y}}; + } + + static void from_json(const json& j, cv::Point& point) { + j.at("x").get_to(point.x); + j.at("y").get_to(point.y); + } + }; + + template <> + struct adl_serializer + { + static void to_json(json& j, const cv::Matx33d& mat) { + for (int row = 0; row < 3; ++row) { + for (int col = 0; col < 3; ++col) { + j[std::to_string(row) + std::to_string(col)] = mat(row, col); + } + } + } + + static void from_json(const json& j, cv::Matx33d& mat) { + for (int row = 0; row < 3; ++row) { + for (int col = 0; col < 3; ++col) { + mat(row, col) = j[std::to_string(row) + std::to_string(col)]; + } + } + } + }; + + template <> + struct adl_serializer + { + static void to_json(json& j, const ImmVision::ColormapScaleFromStatsData& data) { + j = json{ + {"ColorMapStatsType", data.ColorMapStatsType}, + {"NbSigmas", data.NbSigmas}, + {"UseStatsMin", data.UseStatsMin}, + {"UseStatsMax", data.UseStatsMax} + }; + } + + static void from_json(const json& j, ImmVision::ColormapScaleFromStatsData& data) { + j.at("ColorMapStatsType").get_to(data.ColorMapStatsType); + j.at("NbSigmas").get_to(data.NbSigmas); + j.at("UseStatsMin").get_to(data.UseStatsMin); + j.at("UseStatsMax").get_to(data.UseStatsMax); + } + }; + + template <> + struct adl_serializer + { + static void to_json(json& j, const ImmVision::ColormapSettingsData& data) { + j = json{ + {"Colormap", data.Colormap}, + {"ColormapScaleMin", data.ColormapScaleMin}, + {"ColormapScaleMax", data.ColormapScaleMax}, + {"ColormapScaleFromStats", data.ColormapScaleFromStats}, + {"internal_ColormapHovered", data.internal_ColormapHovered} + }; + } + + static void from_json(const json& j, ImmVision::ColormapSettingsData& data) { + j.at("Colormap").get_to(data.Colormap); + j.at("ColormapScaleMin").get_to(data.ColormapScaleMin); + j.at("ColormapScaleMax").get_to(data.ColormapScaleMax); + j.at("ColormapScaleFromStats").get_to(data.ColormapScaleFromStats); + j.at("internal_ColormapHovered").get_to(data.internal_ColormapHovered); + } + }; + + template <> + struct adl_serializer + { + static void to_json(json& j, const ImmVision::ImageParams& params) + { + j = json{ + {"RefreshImage", params.RefreshImage}, + {"ImageDisplaySize", params.ImageDisplaySize}, + {"ZoomPanMatrix", params.ZoomPanMatrix}, + {"ZoomKey", params.ZoomKey}, + {"ColormapSettings", params.ColormapSettings}, + {"ColormapKey", params.ColormapKey}, + {"PanWithMouse", params.PanWithMouse}, + {"ZoomWithMouseWheel", params.ZoomWithMouseWheel}, + {"IsColorOrderBGR", params.IsColorOrderBGR}, + {"SelectedChannel", params.SelectedChannel}, + {"ShowSchoolPaperBackground", params.ShowSchoolPaperBackground}, + {"ShowAlphaChannelCheckerboard", params.ShowAlphaChannelCheckerboard}, + {"ShowGrid", params.ShowGrid}, + {"DrawValuesOnZoomedPixels", params.DrawValuesOnZoomedPixels}, + {"ShowImageInfo", params.ShowImageInfo}, + {"ShowPixelInfo", params.ShowPixelInfo}, + {"ShowZoomButtons", params.ShowZoomButtons}, + {"ShowOptionsPanel", params.ShowOptionsPanel}, + {"ShowOptionsInTooltip", params.ShowOptionsInTooltip}, + {"ShowOptionsButton", params.ShowOptionsButton}, + {"WatchedPixels", params.WatchedPixels}, + {"AddWatchedPixelOnDoubleClick", params.AddWatchedPixelOnDoubleClick}, + {"HighlightWatchedPixels", params.HighlightWatchedPixels} + }; + } + + static void from_json(const json& j, ImmVision::ImageParams& params) + { + j.at("RefreshImage").get_to(params.RefreshImage); + j.at("ImageDisplaySize").get_to(params.ImageDisplaySize); + j.at("ZoomPanMatrix").get_to(params.ZoomPanMatrix); + j.at("ZoomKey").get_to(params.ZoomKey); + j.at("ColormapSettings").get_to(params.ColormapSettings); + j.at("ColormapKey").get_to(params.ColormapKey); + j.at("PanWithMouse").get_to(params.PanWithMouse); + j.at("ZoomWithMouseWheel").get_to(params.ZoomWithMouseWheel); + j.at("IsColorOrderBGR").get_to(params.IsColorOrderBGR); + j.at("SelectedChannel").get_to(params.SelectedChannel); + j.at("ShowSchoolPaperBackground").get_to(params.ShowSchoolPaperBackground); + j.at("ShowAlphaChannelCheckerboard").get_to(params.ShowAlphaChannelCheckerboard); + j.at("ShowGrid").get_to(params.ShowGrid); + j.at("DrawValuesOnZoomedPixels").get_to(params.DrawValuesOnZoomedPixels); + j.at("ShowImageInfo").get_to(params.ShowImageInfo); + j.at("ShowPixelInfo").get_to(params.ShowPixelInfo); + j.at("ShowZoomButtons").get_to(params.ShowZoomButtons); + j.at("ShowOptionsPanel").get_to(params.ShowOptionsPanel); + j.at("ShowOptionsInTooltip").get_to(params.ShowOptionsInTooltip); + j.at("ShowOptionsButton").get_to(params.ShowOptionsButton); + j.at("WatchedPixels").get_to(params.WatchedPixels); + j.at("AddWatchedPixelOnDoubleClick").get_to(params.AddWatchedPixelOnDoubleClick); + j.at("HighlightWatchedPixels").get_to(params.HighlightWatchedPixels); + } + + }; +} // namespace nlohmann + + +namespace ImmVision +{ + using json = nlohmann::json; + + + std::string ImageParamsToJson(const ImageParams& params) + { + json j = params; + return j.dump(4); + } + + void FillImageParamsFromJson(const std::string& json, ImageParams* params) + { + nlohmann::json j = nlohmann::json::parse(json); + nlohmann::adl_serializer::from_json(j, *params); + } + + ImageParams ImageParamsFromJson(const std::string& json) + { + ImageParams params; + FillImageParamsFromJson(json, ¶ms); + return params; + } + +} +#endif + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // src/immvision/internal/imgui/image_widgets.cpp // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src_all_in_one/immvision/immvision.h b/src_all_in_one/immvision/immvision.h index 5056181..3bfa378 100644 --- a/src_all_in_one/immvision/immvision.h +++ b/src_all_in_one/immvision/immvision.h @@ -191,6 +191,11 @@ namespace ImmVision ~ImageParams(); }; +#ifdef IMMVISION_SERIALIZE_JSON + IMMVISION_API std::string ImageParamsToJson(const ImageParams& params); + IMMVISION_API void FillImageParamsFromJson(const std::string& json, ImageParams* params); + IMMVISION_API ImageParams ImageParamsFromJson(const std::string& json); +#endif // Create ImageParams that display the image only, with no decoration, and no user interaction IMMVISION_API ImageParams FactorImageParamsDisplayOnly();