Skip to content

Commit

Permalink
**Breaking change**: Handle default color order
Browse files Browse the repository at this point in the history
  ImmVision now requires you to explicitly set the color order (RGB or BGR) at the start of your program.
  To configure the color order, you must call one of the following **once** before displaying images:
  - In C++: `ImmVision::UseRgbColorOrder()` or `ImmVision::UseBgrColorOrder()`
  - In Python: `immvision.use_rgb_color_order()` or `immvision.use_bgr_color_order()`
  This change ensures that you are explicitly aware of the color order used throughout your program.
  If the color order is not configured, an error will be thrown when attempting to display images.
  The `IsColorOrderBGR` member in `ImageParams` and the corresponding `isBgrOrBgra` parameter in `ImageDisplay` have been **removed**.
  • Loading branch information
pthom committed Oct 6, 2024
1 parent f227386 commit 5d35e1f
Show file tree
Hide file tree
Showing 13 changed files with 159 additions and 118 deletions.
8 changes: 5 additions & 3 deletions src/immdebug_viewer/immdebug_viewer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
5 changes: 3 additions & 2 deletions src/immvision/gl_texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -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;

Expand Down
21 changes: 12 additions & 9 deletions src/immvision/image.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -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 = "";
};
Expand Down Expand Up @@ -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
//
Expand Down Expand Up @@ -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.
Expand All @@ -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)
Expand All @@ -316,8 +320,7 @@ namespace ImmVision
ImVec2* size = nullptr,
bool refreshImage = false,
bool resizable = true,
bool showOptionsButton = false,
bool isBgrOrBgra = true
bool showOptionsButton = false
);


Expand Down
4 changes: 2 additions & 2 deletions src/immvision/inspector.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once
#include <opencv2/core.hpp>
#include <string>
#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
Expand All @@ -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();
Expand Down
5 changes: 4 additions & 1 deletion src/immvision/internal/drawing/image_drawing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

namespace ImmVision
{
bool Priv_IsColorOrderBgr();

namespace ImageDrawing
{
static float _ImmDrawingFontScaleRatio()
Expand Down Expand Up @@ -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);
Expand Down
48 changes: 30 additions & 18 deletions src/immvision/internal/image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#include <map>
#include <vector>
#include <optional>
#include <iostream>

#ifndef IMMVISION_VERSION
Expand All @@ -30,6 +31,30 @@ namespace ImmVision
// since calls to Image & ImageDisplay will have a reproducible id stack
static bool sDoUseIdStack = true;


static std::optional<bool> 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();
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -253,16 +278,6 @@ namespace ImmVision

auto fnImageDisplayOptions_Gui = [&params, &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", &params->ShowSchoolPaperBackground);
if (image.type() == CV_8UC4)
ImGui::Checkbox("Show alpha channel checkerboard", &params->ShowAlphaChannelCheckerboard);
Expand Down Expand Up @@ -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<ImGuiID, ImageParams> s_Params;
Expand All @@ -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);
Expand All @@ -717,8 +731,7 @@ namespace ImmVision
ImVec2* size,
bool refreshImage,
bool resizable,
bool showOptionsButton,
bool isBgrOrBgra
bool showOptionsButton
)
{
if (size == nullptr)
Expand All @@ -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);
Expand Down
4 changes: 0 additions & 4 deletions src/immvision/internal/image_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ namespace ImmVision
return true;
if (v1.ShowSchoolPaperBackground != v2.ShowSchoolPaperBackground)
return true;
if (v1.IsColorOrderBGR != v2.IsColorOrderBGR)
return true;
return false;
}

Expand All @@ -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)
Expand Down
2 changes: 0 additions & 2 deletions src/immvision/internal/image_params_serialize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -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);
Expand Down
8 changes: 6 additions & 2 deletions src/immvision/internal/imgui/image_widgets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

namespace ImmVision
{
bool Priv_IsColorOrderBgr();

namespace ImageWidgets
{
void GlTexture_Draw_DisableDragWindow(const GlTexture& texture, const ImVec2 &size, bool disableDragWindow)
Expand Down Expand Up @@ -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, &params](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, &params](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]));
};
Expand Down
4 changes: 1 addition & 3 deletions src/immvision/internal/inspector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 1 addition & 2 deletions src/immvision/internal/misc/immvision_to_string.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ namespace ImmVision
r += "}";
return r;
}

std::string ToString(const ImageParams& v)
{

Expand All @@ -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";
Expand Down
Loading

0 comments on commit 5d35e1f

Please sign in to comment.