diff --git a/src/immdebug_viewer/immdebug_viewer.cpp b/src/immdebug_viewer/immdebug_viewer.cpp index 5b8bc7e..5fb3098 100644 --- a/src/immdebug_viewer/immdebug_viewer.cpp +++ b/src/immdebug_viewer/immdebug_viewer.cpp @@ -17,15 +17,17 @@ void AddIncomingImages() if (imagePayload) { HelloImGui::Log(HelloImGui::LogLevel::Info, "Received image payload"); - + if (imagePayload->isColorOrderBGR) + ImmVision::UseBgrColorOrder(); + else + ImmVision::UseRgbColorOrder(); ImmVision::Inspector_AddImage( imagePayload->Image, imagePayload->Legend, imagePayload->ZoomKey, imagePayload->ColorAdjustmentsKey, imagePayload->ZoomCenter, - imagePayload->ZoomRatio, - imagePayload->isColorOrderBGR + imagePayload->ZoomRatio ); foundNewImages = true; } diff --git a/src/immvision/gl_texture.h b/src/immvision/gl_texture.h index 7f973e6..b70b0f0 100644 --- a/src/immvision/gl_texture.h +++ b/src/immvision/gl_texture.h @@ -15,7 +15,8 @@ namespace ImmVision // Create an empty texture GlTexture(); // Create a texture from an image (cv::Mat in C++, numpy array in Python) - GlTexture(const cv::Mat& image, bool isColorOrderBGR); + // isColorOrderBGR: if true, the image is assumed to be in BGR order (OpenCV default) + GlTexture(const cv::Mat& image, bool isColorOrderBGR = false); // The destructor will delete the texture from the GPU ~GlTexture(); @@ -32,7 +33,7 @@ namespace ImmVision // // Update the texture from a new image (cv::Mat in C++, numpy array in Python). - void UpdateFromImage(const cv::Mat& image, bool isColorOrderBGR); + void UpdateFromImage(const cv::Mat& image, bool isColorOrderBGR = false); // Returns the size as ImVec2 ImVec2 SizeImVec2() const; diff --git a/src/immvision/image.h b/src/immvision/image.h index 3f32f86..32ba512 100644 --- a/src/immvision/image.h +++ b/src/immvision/image.h @@ -22,6 +22,14 @@ namespace ImmVision FromVisibleROI }; + // Set the color order for displayed images. + // You **must** call once at the start of your program: + // ImmVision::UseRgbColorOrder() or ImmVision::UseBgrColorOrder() (C++) + // immvision.use_rgb_color_order() or immvision.use_bgr_color_order() (Python) + // (Breaking change - October 2024) + void UseRgbColorOrder(); + void UseBgrColorOrder(); + // Scale the Colormap according to the Image stats struct ColormapScaleFromStatsData // IMMVISION_API_STRUCT { @@ -58,7 +66,6 @@ namespace ImmVision // ColormapScaleFromStats.ActiveOnFullImage is true by default ColormapScaleFromStatsData ColormapScaleFromStats = ColormapScaleFromStatsData(); - // Internal value: stores the name of the Colormap that is hovered by the mouse std::string internal_ColormapHovered = ""; }; @@ -139,9 +146,6 @@ namespace ImmVision // Does the widget keep an aspect ratio equal to the image when resized bool ResizeKeepAspectRatio = true; - // Color Order: RGB or RGBA versus BGR or BGRA (Note: by default OpenCV uses BGR and BGRA) - bool IsColorOrderBGR = true; - // // Image display options // @@ -285,7 +289,8 @@ namespace ImmVision // In that case, it also becomes possible to zoom & pan, add watched pixel by double-clicking, etc. // // :param isBgrOrBgra: - // set to true if the color order of the image is BGR or BGRA (as in OpenCV, by default) + // set to true if the color order of the image is BGR or BGRA (as in OpenCV) + //. Breaking change, oct 2024: the default is BGR for C++, RGB for Python! // // :return: // The mouse position in `mat` original image coordinates, as double values. @@ -303,8 +308,7 @@ namespace ImmVision const cv::Mat& mat, const cv::Size& imageDisplaySize = cv::Size(), bool refreshImage = false, - bool showOptionsButton = false, - bool isBgrOrBgra = true + bool showOptionsButton = false ); // ImageDisplayResizable: display the image, with no user interaction (by default) @@ -316,8 +320,7 @@ namespace ImmVision ImVec2* size = nullptr, bool refreshImage = false, bool resizable = true, - bool showOptionsButton = false, - bool isBgrOrBgra = true + bool showOptionsButton = false ); diff --git a/src/immvision/inspector.h b/src/immvision/inspector.h index 0872555..33b6b22 100644 --- a/src/immvision/inspector.h +++ b/src/immvision/inspector.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include "immvision/image.h" // IMMVISION_API is a marker for public API functions. IMMVISION_STRUCT_API is a marker for public API structs (in comment lines) // Usage of ImmVision as a shared library is not recommended. No guaranty of ABI stability is provided @@ -16,8 +17,7 @@ namespace ImmVision const std::string& zoomKey = "", const std::string& colormapKey = "", const cv::Point2d & zoomCenter = cv::Point2d(), - double zoomRatio = -1., - bool isColorOrderBGR = true + double zoomRatio = -1. ); IMMVISION_API void Inspector_Show(); diff --git a/src/immvision/internal/drawing/image_drawing.cpp b/src/immvision/internal/drawing/image_drawing.cpp index 29febcb..b93f60f 100644 --- a/src/immvision/internal/drawing/image_drawing.cpp +++ b/src/immvision/internal/drawing/image_drawing.cpp @@ -11,6 +11,8 @@ namespace ImmVision { + bool Priv_IsColorOrderBgr(); + namespace ImageDrawing { static float _ImmDrawingFontScaleRatio() @@ -218,7 +220,8 @@ namespace ImmVision { fnSelectChannel(); fnAlphaCheckerboard(); - finalImage = CvDrawingUtils::converted_to_rgba_image(finalImage, params.IsColorOrderBGR); + bool is_color_order_bgr = Priv_IsColorOrderBgr(); + finalImage = CvDrawingUtils::converted_to_rgba_image(finalImage, is_color_order_bgr); } in_out_rgba_image_cache = finalImage; assert(finalImage.type() == CV_8UC4); diff --git a/src/immvision/internal/image.cpp b/src/immvision/internal/image.cpp index 5a5ebb3..d9d0bc2 100644 --- a/src/immvision/internal/image.cpp +++ b/src/immvision/internal/image.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #ifndef IMMVISION_VERSION @@ -30,6 +31,30 @@ namespace ImmVision // since calls to Image & ImageDisplay will have a reproducible id stack static bool sDoUseIdStack = true; + + static std::optional sUseBgrOrder = std::nullopt; + void UseRgbColorOrder() { sUseBgrOrder = false; } + void UseBgrColorOrder() { sUseBgrOrder = true; } + bool Priv_IsColorOrderBgr() + { + const char* errorMessage = R"( +Error in ImmVision +================== +You must set the image color order before displaying images. At the start of your program, call: + ImmVision::UseRgbColorOrder() or ImmVision::UseBgrColorOrder() (C++) +or + immvision.use_rgb_color_order() or immvision.use_bgr_color_order() (Python) + +This is a required setup step. (Breaking change - October 2024) +)"; + if (!sUseBgrOrder.has_value()) + { + fprintf(stderr, "%s", errorMessage); + throw std::runtime_error(errorMessage); + } + return sUseBgrOrder.value(); + } + void ClearTextureCache() { ImageCache::gImageTextureCache.ClearImagesCache(); @@ -166,12 +191,12 @@ namespace ImmVision cv::Mat imageAsSaved = image; // image with possible RGB2BGR conversion if (image.type() == CV_8UC3) { - if (!params->IsColorOrderBGR) + if (!Priv_IsColorOrderBgr()) cv::cvtColor(image, imageAsSaved, cv::COLOR_RGB2BGR); } if (image.type() == CV_8UC4) { - if (!params->IsColorOrderBGR) + if (!Priv_IsColorOrderBgr()) cv::cvtColor(image, imageAsSaved, cv::COLOR_RGBA2BGRA); } return imageAsSaved; @@ -253,16 +278,6 @@ namespace ImmVision auto fnImageDisplayOptions_Gui = [¶ms, &image]() { - if (image.type() == CV_8UC3 || image.type() == CV_8UC4) - { - ImGui::Text("Color Order"); - ImGui::SameLine(); - int v = params->IsColorOrderBGR ? 0 : 1; - ImGui::RadioButton("RGB", &v, 1); - ImGui::SameLine(); - ImGui::RadioButton("BGR", &v, 0); - params->IsColorOrderBGR = (v == 0); - } ImGui::Checkbox("Show school paper background", ¶ms->ShowSchoolPaperBackground); if (image.type() == CV_8UC4) ImGui::Checkbox("Show alpha channel checkerboard", ¶ms->ShowAlphaChannelCheckerboard); @@ -682,8 +697,8 @@ namespace ImmVision const cv::Mat& mat, const cv::Size& imageDisplaySize, bool refreshImage, - bool showOptionsButton, - bool isBgrOrBgra) + bool showOptionsButton + ) { ImGuiID id = ImGui::GetID(label_id.c_str()); static std::map s_Params; @@ -698,7 +713,6 @@ namespace ImmVision params.ShowOptionsButton = showOptionsButton; params.ImageDisplaySize = imageDisplaySize; params.RefreshImage = refreshImage; - params.IsColorOrderBGR = isBgrOrBgra; cv::Size displayedSize = ImGuiImm::ComputeDisplayImageSize(imageDisplaySize, mat.size()); params.ZoomPanMatrix = ZoomPanTransform::MakeFullView(mat.size(), displayedSize); @@ -717,8 +731,7 @@ namespace ImmVision ImVec2* size, bool refreshImage, bool resizable, - bool showOptionsButton, - bool isBgrOrBgra + bool showOptionsButton ) { if (size == nullptr) @@ -744,7 +757,6 @@ namespace ImmVision params.ImageDisplaySize = imageDisplaySize; params.CanResize = resizable; params.RefreshImage = refreshImage; - params.IsColorOrderBGR = isBgrOrBgra; cv::Size displayedSize = ImGuiImm::ComputeDisplayImageSize(imageDisplaySize, mat.size()); params.ZoomPanMatrix = ZoomPanTransform::MakeFullView(mat.size(), displayedSize); diff --git a/src/immvision/internal/image_cache.cpp b/src/immvision/internal/image_cache.cpp index 9b0669a..dec704a 100644 --- a/src/immvision/internal/image_cache.cpp +++ b/src/immvision/internal/image_cache.cpp @@ -44,8 +44,6 @@ namespace ImmVision return true; if (v1.ShowSchoolPaperBackground != v2.ShowSchoolPaperBackground) return true; - if (v1.IsColorOrderBGR != v2.IsColorOrderBGR) - return true; return false; } @@ -67,8 +65,6 @@ namespace ImmVision return true; if (v1.ShowSchoolPaperBackground != v2.ShowSchoolPaperBackground) return true; - if (v1.IsColorOrderBGR != v2.IsColorOrderBGR) - return true; if (v1.WatchedPixels.size() != v2.WatchedPixels.size()) return true; if (v1.HighlightWatchedPixels != v2.HighlightWatchedPixels) diff --git a/src/immvision/internal/image_params_serialize.cpp b/src/immvision/internal/image_params_serialize.cpp index 58dd0c2..6b184a6 100644 --- a/src/immvision/internal/image_params_serialize.cpp +++ b/src/immvision/internal/image_params_serialize.cpp @@ -107,7 +107,6 @@ namespace nlohmann {"ColormapKey", params.ColormapKey}, {"PanWithMouse", params.PanWithMouse}, {"ZoomWithMouseWheel", params.ZoomWithMouseWheel}, - {"IsColorOrderBGR", params.IsColorOrderBGR}, {"SelectedChannel", params.SelectedChannel}, {"ShowSchoolPaperBackground", params.ShowSchoolPaperBackground}, {"ShowAlphaChannelCheckerboard", params.ShowAlphaChannelCheckerboard}, @@ -135,7 +134,6 @@ namespace nlohmann 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); diff --git a/src/immvision/internal/imgui/image_widgets.cpp b/src/immvision/internal/imgui/image_widgets.cpp index b6d7b1e..5598529 100644 --- a/src/immvision/internal/imgui/image_widgets.cpp +++ b/src/immvision/internal/imgui/image_widgets.cpp @@ -5,6 +5,8 @@ namespace ImmVision { + bool Priv_IsColorOrderBgr(); + namespace ImageWidgets { void GlTexture_Draw_DisableDragWindow(const GlTexture& texture, const ImVec2 &size, bool disableDragWindow) @@ -57,12 +59,14 @@ namespace ImmVision bool isInImage = cv::Rect(cv::Point(0, 0), image.size()).contains((pt)); auto UCharToFloat = [](int v) { return (float)((float) v / 255.f); }; auto Vec3bToImVec4 = [&UCharToFloat, ¶ms](cv::Vec3b v) { - return params.IsColorOrderBGR ? + bool isColorOrderBgr = Priv_IsColorOrderBgr(); + return isColorOrderBgr ? ImVec4(UCharToFloat(v[2]), UCharToFloat(v[1]), UCharToFloat(v[0]), UCharToFloat(255)) : ImVec4(UCharToFloat(v[0]), UCharToFloat(v[1]), UCharToFloat(v[2]), UCharToFloat(255)); }; auto Vec4bToImVec4 = [&UCharToFloat, ¶ms](cv::Vec4b v) { - return params.IsColorOrderBGR ? + bool isColorOrderBgr = Priv_IsColorOrderBgr(); + return isColorOrderBgr ? ImVec4(UCharToFloat(v[2]), UCharToFloat(v[1]), UCharToFloat(v[0]), UCharToFloat(v[3])) : ImVec4(UCharToFloat(v[0]), UCharToFloat(v[1]), UCharToFloat(v[2]), UCharToFloat(v[3])); }; diff --git a/src/immvision/internal/inspector.cpp b/src/immvision/internal/inspector.cpp index f8141b9..3946534 100644 --- a/src/immvision/internal/inspector.cpp +++ b/src/immvision/internal/inspector.cpp @@ -38,12 +38,10 @@ namespace ImmVision const std::string& zoomKey, const std::string& colormapKey, const cv::Point2d & zoomCenter, - double zoomRatio, - bool isColorOrderBGR + double zoomRatio ) { ImageParams params; - params.IsColorOrderBGR = isColorOrderBGR; params.ZoomKey = zoomKey; params.ColormapKey = colormapKey; params.ShowOptionsPanel = true; diff --git a/src/immvision/internal/misc/immvision_to_string.cpp b/src/immvision/internal/misc/immvision_to_string.cpp index b39c780..d71afd3 100644 --- a/src/immvision/internal/misc/immvision_to_string.cpp +++ b/src/immvision/internal/misc/immvision_to_string.cpp @@ -73,7 +73,7 @@ namespace ImmVision r += "}"; return r; } - + std::string ToString(const ImageParams& v) { @@ -93,7 +93,6 @@ namespace ImmVision inner = inner + "ColormapKey: " + ToString(v.ColormapKey) + "\n"; inner = inner + "PanWithMouse: " + ToString(v.PanWithMouse) + "\n"; inner = inner + "ZoomWithMouseWheel: " + ToString(v.ZoomWithMouseWheel) + "\n"; - inner = inner + "IsColorOrderBGR: " + ToString(v.IsColorOrderBGR) + "\n"; inner = inner + "SelectedChannel: " + ToString(v.SelectedChannel) + "\n"; inner = inner + "ShowSchoolPaperBackground: " + ToString(v.ShowSchoolPaperBackground) + "\n"; inner = inner + "ShowAlphaChannelCheckerboard: " + ToString(v.ShowAlphaChannelCheckerboard) + "\n"; diff --git a/src_all_in_one/immvision/immvision.cpp b/src_all_in_one/immvision/immvision.cpp index 007a35c..870f2cc 100644 --- a/src_all_in_one/immvision/immvision.cpp +++ b/src_all_in_one/immvision/immvision.cpp @@ -35,6 +35,14 @@ namespace ImmVision FromVisibleROI }; + // Set the color order for displayed images. + // You **must** call once at the start of your program: + // ImmVision::UseRgbColorOrder() or ImmVision::UseBgrColorOrder() (C++) + // immvision.use_rgb_color_order() or immvision.use_bgr_color_order() (Python) + // (Breaking change - October 2024) + void UseRgbColorOrder(); + void UseBgrColorOrder(); + // Scale the Colormap according to the Image stats struct ColormapScaleFromStatsData // IMMVISION_API_STRUCT { @@ -71,7 +79,6 @@ namespace ImmVision // ColormapScaleFromStats.ActiveOnFullImage is true by default ColormapScaleFromStatsData ColormapScaleFromStats = ColormapScaleFromStatsData(); - // Internal value: stores the name of the Colormap that is hovered by the mouse std::string internal_ColormapHovered = ""; }; @@ -152,9 +159,6 @@ namespace ImmVision // Does the widget keep an aspect ratio equal to the image when resized bool ResizeKeepAspectRatio = true; - // Color Order: RGB or RGBA versus BGR or BGRA (Note: by default OpenCV uses BGR and BGRA) - bool IsColorOrderBGR = true; - // // Image display options // @@ -298,7 +302,8 @@ namespace ImmVision // In that case, it also becomes possible to zoom & pan, add watched pixel by double-clicking, etc. // // :param isBgrOrBgra: - // set to true if the color order of the image is BGR or BGRA (as in OpenCV, by default) + // set to true if the color order of the image is BGR or BGRA (as in OpenCV) + //. Breaking change, oct 2024: the default is BGR for C++, RGB for Python! // // :return: // The mouse position in `mat` original image coordinates, as double values. @@ -316,8 +321,7 @@ namespace ImmVision const cv::Mat& mat, const cv::Size& imageDisplaySize = cv::Size(), bool refreshImage = false, - bool showOptionsButton = false, - bool isBgrOrBgra = true + bool showOptionsButton = false ); // ImageDisplayResizable: display the image, with no user interaction (by default) @@ -329,8 +333,7 @@ namespace ImmVision ImVec2* size = nullptr, bool refreshImage = false, bool resizable = true, - bool showOptionsButton = false, - bool isBgrOrBgra = true + bool showOptionsButton = false ); @@ -4489,7 +4492,8 @@ namespace ImmVision // Create an empty texture GlTexture(); // Create a texture from an image (cv::Mat in C++, numpy array in Python) - GlTexture(const cv::Mat& image, bool isColorOrderBGR); + // isColorOrderBGR: if true, the image is assumed to be in BGR order (OpenCV default) + GlTexture(const cv::Mat& image, bool isColorOrderBGR = false); // The destructor will delete the texture from the GPU ~GlTexture(); @@ -4506,7 +4510,7 @@ namespace ImmVision // // Update the texture from a new image (cv::Mat in C++, numpy array in Python). - void UpdateFromImage(const cv::Mat& image, bool isColorOrderBGR); + void UpdateFromImage(const cv::Mat& image, bool isColorOrderBGR = false); // Returns the size as ImVec2 ImVec2 SizeImVec2() const; @@ -5956,18 +5960,28 @@ namespace ImmVision { std::string _MatTypeName(const cv::Mat& m) { - std::map depthNames - { - { CV_8U, "CV_8U" }, - { CV_8S, "CV_8S" }, - { CV_16U, "CV_16U" }, - { CV_16S, "CV_16S" }, - { CV_32S, "CV_32S"}, - { CV_32F, "CV_32F"}, - { CV_64F, "CV_64F"}, - { CV_16F, "CV_16F"} - }; - return depthNames.at(m.depth()) + "C" + std::to_string(m.channels()); + int depth = m.depth(); + if (depth == CV_8U) + return "uint8"; + else if (depth == CV_8S) + return "int8"; + else if (depth == CV_16U) + return "uint16"; + else if (depth == CV_16S) + return "int16"; + else if (depth == CV_32S) + return "int32"; + else if (depth == CV_32F) + return "float32"; + else if (depth == CV_64F) + return "float64"; + else if (depth == CV_16F) + return "float16"; + else + { + printf("Unhandled depth: %d\n", depth); + return "???"; + } } std::string _MatInfo(const cv::Mat &m) @@ -6382,6 +6396,8 @@ namespace ImmVision namespace ImmVision { + bool Priv_IsColorOrderBgr(); + namespace ImageDrawing { static float _ImmDrawingFontScaleRatio() @@ -6589,7 +6605,8 @@ namespace ImmVision { fnSelectChannel(); fnAlphaCheckerboard(); - finalImage = CvDrawingUtils::converted_to_rgba_image(finalImage, params.IsColorOrderBGR); + bool is_color_order_bgr = Priv_IsColorOrderBgr(); + finalImage = CvDrawingUtils::converted_to_rgba_image(finalImage, is_color_order_bgr); } in_out_rgba_image_cache = finalImage; assert(finalImage.type() == CV_8UC4); @@ -9455,8 +9472,7 @@ namespace ImmVision const std::string& zoomKey = "", const std::string& colormapKey = "", const cv::Point2d & zoomCenter = cv::Point2d(), - double zoomRatio = -1., - bool isColorOrderBGR = true + double zoomRatio = -1. ); IMMVISION_API void Inspector_Show(); @@ -9479,6 +9495,30 @@ namespace ImmVision // since calls to Image & ImageDisplay will have a reproducible id stack static bool sDoUseIdStack = true; + + static std::optional sUseBgrOrder = std::nullopt; + void UseRgbColorOrder() { sUseBgrOrder = false; } + void UseBgrColorOrder() { sUseBgrOrder = true; } + bool Priv_IsColorOrderBgr() + { + const char* errorMessage = R"( +Error in ImmVision +================== +You must set the image color order before displaying images. At the start of your program, call: + ImmVision::UseRgbColorOrder() or ImmVision::UseBgrColorOrder() (C++) +or + immvision.use_rgb_color_order() or immvision.use_bgr_color_order() (Python) + +This is a required setup step. (Breaking change - October 2024) +)"; + if (!sUseBgrOrder.has_value()) + { + fprintf(stderr, "%s", errorMessage); + throw std::runtime_error(errorMessage); + } + return sUseBgrOrder.value(); + } + void ClearTextureCache() { ImageCache::gImageTextureCache.ClearImagesCache(); @@ -9615,12 +9655,12 @@ namespace ImmVision cv::Mat imageAsSaved = image; // image with possible RGB2BGR conversion if (image.type() == CV_8UC3) { - if (!params->IsColorOrderBGR) + if (!Priv_IsColorOrderBgr()) cv::cvtColor(image, imageAsSaved, cv::COLOR_RGB2BGR); } if (image.type() == CV_8UC4) { - if (!params->IsColorOrderBGR) + if (!Priv_IsColorOrderBgr()) cv::cvtColor(image, imageAsSaved, cv::COLOR_RGBA2BGRA); } return imageAsSaved; @@ -9702,16 +9742,6 @@ namespace ImmVision auto fnImageDisplayOptions_Gui = [¶ms, &image]() { - if (image.type() == CV_8UC3 || image.type() == CV_8UC4) - { - ImGui::Text("Color Order"); - ImGui::SameLine(); - int v = params->IsColorOrderBGR ? 0 : 1; - ImGui::RadioButton("RGB", &v, 1); - ImGui::SameLine(); - ImGui::RadioButton("BGR", &v, 0); - params->IsColorOrderBGR = (v == 0); - } ImGui::Checkbox("Show school paper background", ¶ms->ShowSchoolPaperBackground); if (image.type() == CV_8UC4) ImGui::Checkbox("Show alpha channel checkerboard", ¶ms->ShowAlphaChannelCheckerboard); @@ -10131,8 +10161,8 @@ namespace ImmVision const cv::Mat& mat, const cv::Size& imageDisplaySize, bool refreshImage, - bool showOptionsButton, - bool isBgrOrBgra) + bool showOptionsButton + ) { ImGuiID id = ImGui::GetID(label_id.c_str()); static std::map s_Params; @@ -10147,7 +10177,6 @@ namespace ImmVision params.ShowOptionsButton = showOptionsButton; params.ImageDisplaySize = imageDisplaySize; params.RefreshImage = refreshImage; - params.IsColorOrderBGR = isBgrOrBgra; cv::Size displayedSize = ImGuiImm::ComputeDisplayImageSize(imageDisplaySize, mat.size()); params.ZoomPanMatrix = ZoomPanTransform::MakeFullView(mat.size(), displayedSize); @@ -10166,8 +10195,7 @@ namespace ImmVision ImVec2* size, bool refreshImage, bool resizable, - bool showOptionsButton, - bool isBgrOrBgra + bool showOptionsButton ) { if (size == nullptr) @@ -10193,7 +10221,6 @@ namespace ImmVision params.ImageDisplaySize = imageDisplaySize; params.CanResize = resizable; params.RefreshImage = refreshImage; - params.IsColorOrderBGR = isBgrOrBgra; cv::Size displayedSize = ImGuiImm::ComputeDisplayImageSize(imageDisplaySize, mat.size()); params.ZoomPanMatrix = ZoomPanTransform::MakeFullView(mat.size(), displayedSize); @@ -10300,8 +10327,6 @@ namespace ImmVision return true; if (v1.ShowSchoolPaperBackground != v2.ShowSchoolPaperBackground) return true; - if (v1.IsColorOrderBGR != v2.IsColorOrderBGR) - return true; return false; } @@ -10323,8 +10348,6 @@ namespace ImmVision return true; if (v1.ShowSchoolPaperBackground != v2.ShowSchoolPaperBackground) return true; - if (v1.IsColorOrderBGR != v2.IsColorOrderBGR) - return true; if (v1.WatchedPixels.size() != v2.WatchedPixels.size()) return true; if (v1.HighlightWatchedPixels != v2.HighlightWatchedPixels) @@ -10654,7 +10677,6 @@ namespace nlohmann {"ColormapKey", params.ColormapKey}, {"PanWithMouse", params.PanWithMouse}, {"ZoomWithMouseWheel", params.ZoomWithMouseWheel}, - {"IsColorOrderBGR", params.IsColorOrderBGR}, {"SelectedChannel", params.SelectedChannel}, {"ShowSchoolPaperBackground", params.ShowSchoolPaperBackground}, {"ShowAlphaChannelCheckerboard", params.ShowAlphaChannelCheckerboard}, @@ -10682,7 +10704,6 @@ namespace nlohmann 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); @@ -10738,6 +10759,8 @@ namespace ImmVision namespace ImmVision { + bool Priv_IsColorOrderBgr(); + namespace ImageWidgets { void GlTexture_Draw_DisableDragWindow(const GlTexture& texture, const ImVec2 &size, bool disableDragWindow) @@ -10790,12 +10813,14 @@ namespace ImmVision bool isInImage = cv::Rect(cv::Point(0, 0), image.size()).contains((pt)); auto UCharToFloat = [](int v) { return (float)((float) v / 255.f); }; auto Vec3bToImVec4 = [&UCharToFloat, ¶ms](cv::Vec3b v) { - return params.IsColorOrderBGR ? + bool isColorOrderBgr = Priv_IsColorOrderBgr(); + return isColorOrderBgr ? ImVec4(UCharToFloat(v[2]), UCharToFloat(v[1]), UCharToFloat(v[0]), UCharToFloat(255)) : ImVec4(UCharToFloat(v[0]), UCharToFloat(v[1]), UCharToFloat(v[2]), UCharToFloat(255)); }; auto Vec4bToImVec4 = [&UCharToFloat, ¶ms](cv::Vec4b v) { - return params.IsColorOrderBGR ? + bool isColorOrderBgr = Priv_IsColorOrderBgr(); + return isColorOrderBgr ? ImVec4(UCharToFloat(v[2]), UCharToFloat(v[1]), UCharToFloat(v[0]), UCharToFloat(v[3])) : ImVec4(UCharToFloat(v[0]), UCharToFloat(v[1]), UCharToFloat(v[2]), UCharToFloat(v[3])); }; @@ -11610,12 +11635,10 @@ namespace ImmVision const std::string& zoomKey, const std::string& colormapKey, const cv::Point2d & zoomCenter, - double zoomRatio, - bool isColorOrderBGR + double zoomRatio ) { ImageParams params; - params.IsColorOrderBGR = isColorOrderBGR; params.ZoomKey = zoomKey; params.ColormapKey = colormapKey; params.ShowOptionsPanel = true; @@ -11920,7 +11943,7 @@ namespace ImmVision r += "}"; return r; } - + std::string ToString(const ImageParams& v) { @@ -11940,7 +11963,6 @@ namespace ImmVision inner = inner + "ColormapKey: " + ToString(v.ColormapKey) + "\n"; inner = inner + "PanWithMouse: " + ToString(v.PanWithMouse) + "\n"; inner = inner + "ZoomWithMouseWheel: " + ToString(v.ZoomWithMouseWheel) + "\n"; - inner = inner + "IsColorOrderBGR: " + ToString(v.IsColorOrderBGR) + "\n"; inner = inner + "SelectedChannel: " + ToString(v.SelectedChannel) + "\n"; inner = inner + "ShowSchoolPaperBackground: " + ToString(v.ShowSchoolPaperBackground) + "\n"; inner = inner + "ShowAlphaChannelCheckerboard: " + ToString(v.ShowAlphaChannelCheckerboard) + "\n"; diff --git a/src_all_in_one/immvision/immvision.h b/src_all_in_one/immvision/immvision.h index 09d1811..6428dfb 100644 --- a/src_all_in_one/immvision/immvision.h +++ b/src_all_in_one/immvision/immvision.h @@ -30,6 +30,14 @@ namespace ImmVision FromVisibleROI }; + // Set the color order for displayed images. + // You **must** call once at the start of your program: + // ImmVision::UseRgbColorOrder() or ImmVision::UseBgrColorOrder() (C++) + // immvision.use_rgb_color_order() or immvision.use_bgr_color_order() (Python) + // (Breaking change - October 2024) + void UseRgbColorOrder(); + void UseBgrColorOrder(); + // Scale the Colormap according to the Image stats struct ColormapScaleFromStatsData // IMMVISION_API_STRUCT { @@ -66,7 +74,6 @@ namespace ImmVision // ColormapScaleFromStats.ActiveOnFullImage is true by default ColormapScaleFromStatsData ColormapScaleFromStats = ColormapScaleFromStatsData(); - // Internal value: stores the name of the Colormap that is hovered by the mouse std::string internal_ColormapHovered = ""; }; @@ -147,9 +154,6 @@ namespace ImmVision // Does the widget keep an aspect ratio equal to the image when resized bool ResizeKeepAspectRatio = true; - // Color Order: RGB or RGBA versus BGR or BGRA (Note: by default OpenCV uses BGR and BGRA) - bool IsColorOrderBGR = true; - // // Image display options // @@ -293,7 +297,8 @@ namespace ImmVision // In that case, it also becomes possible to zoom & pan, add watched pixel by double-clicking, etc. // // :param isBgrOrBgra: - // set to true if the color order of the image is BGR or BGRA (as in OpenCV, by default) + // set to true if the color order of the image is BGR or BGRA (as in OpenCV) + //. Breaking change, oct 2024: the default is BGR for C++, RGB for Python! // // :return: // The mouse position in `mat` original image coordinates, as double values. @@ -311,8 +316,7 @@ namespace ImmVision const cv::Mat& mat, const cv::Size& imageDisplaySize = cv::Size(), bool refreshImage = false, - bool showOptionsButton = false, - bool isBgrOrBgra = true + bool showOptionsButton = false ); // ImageDisplayResizable: display the image, with no user interaction (by default) @@ -324,8 +328,7 @@ namespace ImmVision ImVec2* size = nullptr, bool refreshImage = false, bool resizable = true, - bool showOptionsButton = false, - bool isBgrOrBgra = true + bool showOptionsButton = false ); @@ -373,8 +376,7 @@ namespace ImmVision const std::string& zoomKey = "", const std::string& colormapKey = "", const cv::Point2d & zoomCenter = cv::Point2d(), - double zoomRatio = -1., - bool isColorOrderBGR = true + double zoomRatio = -1. ); IMMVISION_API void Inspector_Show(); @@ -403,7 +405,8 @@ namespace ImmVision // Create an empty texture GlTexture(); // Create a texture from an image (cv::Mat in C++, numpy array in Python) - GlTexture(const cv::Mat& image, bool isColorOrderBGR); + // isColorOrderBGR: if true, the image is assumed to be in BGR order (OpenCV default) + GlTexture(const cv::Mat& image, bool isColorOrderBGR = false); // The destructor will delete the texture from the GPU ~GlTexture(); @@ -420,7 +423,7 @@ namespace ImmVision // // Update the texture from a new image (cv::Mat in C++, numpy array in Python). - void UpdateFromImage(const cv::Mat& image, bool isColorOrderBGR); + void UpdateFromImage(const cv::Mat& image, bool isColorOrderBGR = false); // Returns the size as ImVec2 ImVec2 SizeImVec2() const;