From fc039f239875e2574dc87c7d56cd508de70b6442 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Mon, 27 Jul 2026 11:08:04 +0200 Subject: [PATCH 1/3] take the style of the GUI to draw the matrix --- .../imgui/BaseMatrixImageProxyWidget.cpp | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/applications/plugins/SofaMatrix/extensions/imgui/src/SofaMatrix/imgui/BaseMatrixImageProxyWidget.cpp b/applications/plugins/SofaMatrix/extensions/imgui/src/SofaMatrix/imgui/BaseMatrixImageProxyWidget.cpp index 5f58d5aacbc..23c526dced5 100644 --- a/applications/plugins/SofaMatrix/extensions/imgui/src/SofaMatrix/imgui/BaseMatrixImageProxyWidget.cpp +++ b/applications/plugins/SofaMatrix/extensions/imgui/src/SofaMatrix/imgui/BaseMatrixImageProxyWidget.cpp @@ -82,20 +82,48 @@ void updateTexture(sofa::linearalgebra::BaseMatrix* matrix, unsigned& textureIDR const auto width = matrix->rows(); const auto height = matrix->cols(); - imageDataRef.resize(width * height, 255); + imageDataRef.resize(width * height * 3, 255); + + const ImVec4 colorTrue = ImGui::GetStyleColorVec4(ImGuiCol_Text); + const ImVec4 colorFalse = ImGui::GetStyleColorVec4(ImGuiCol_WindowBg); + + // Extract R, G, B components + const unsigned char rTrue = static_cast(255.f * colorTrue.x); + const unsigned char gTrue = static_cast(255.f * colorTrue.y); + const unsigned char bTrue = static_cast(255.f * colorTrue.z); + + const unsigned char rFalse = static_cast(255.f * colorFalse.x); + const unsigned char gFalse = static_cast(255.f * colorFalse.y); + const unsigned char bFalse = static_cast(255.f * colorFalse.z); // write the data for (sofa::SignedIndex y = 0; y < height; ++y) { for (sofa::SignedIndex x = 0; x < width; ++x) { - imageDataRef[y * width + x] = !static_cast(matrix->element(x, y)) * std::numeric_limits::max(); + size_t index = (y * width + x) * 3; + + // Determine the color based on matrix element value + if (matrix->element(x, y)) + { + // Element is TRUE: Use Window Background Color + imageDataRef[index] = rTrue; // R + imageDataRef[index + 1] = gTrue; // G + imageDataRef[index + 2] = bTrue; // B + } + else + { + // Element is FALSE: Use Text Color + imageDataRef[index] = rFalse; // R + imageDataRef[index + 1] = gFalse; // G + imageDataRef[index + 2] = bFalse; // B + } } } // Update the texture glBindTexture(GL_TEXTURE_2D, textureIDRef); - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, imageDataRef.data()); } From fafccb53bf8d63a631e0b9d6585a6218c1ca5f4f Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Mon, 27 Jul 2026 11:28:25 +0200 Subject: [PATCH 2/3] select colors --- .../imgui/BaseMatrixImageProxyWidget.cpp | 39 +++++++++++++++++-- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/applications/plugins/SofaMatrix/extensions/imgui/src/SofaMatrix/imgui/BaseMatrixImageProxyWidget.cpp b/applications/plugins/SofaMatrix/extensions/imgui/src/SofaMatrix/imgui/BaseMatrixImageProxyWidget.cpp index 23c526dced5..df515254ebc 100644 --- a/applications/plugins/SofaMatrix/extensions/imgui/src/SofaMatrix/imgui/BaseMatrixImageProxyWidget.cpp +++ b/applications/plugins/SofaMatrix/extensions/imgui/src/SofaMatrix/imgui/BaseMatrixImageProxyWidget.cpp @@ -19,10 +19,11 @@ * * * Contact information: contact@sofa-framework.org * ******************************************************************************/ -#include -#include #include +#include #include +#include +#include #include @@ -76,6 +77,18 @@ std::optional textureID(sofa::linearalgebra::BaseMatrix* ptr) return mapIt->second; } +ImVec4& getColorNonZero() +{ + static ImVec4 color = ImGui::GetStyleColorVec4(ImGuiCol_Text); + return color; +} + +ImVec4& getColorZero() +{ + static ImVec4 color = ImGui::GetStyleColorVec4(ImGuiCol_WindowBg); + return color; +} + void updateTexture(sofa::linearalgebra::BaseMatrix* matrix, unsigned& textureIDRef, std::vector& imageDataRef) { @@ -84,8 +97,8 @@ void updateTexture(sofa::linearalgebra::BaseMatrix* matrix, unsigned& textureIDR imageDataRef.resize(width * height * 3, 255); - const ImVec4 colorTrue = ImGui::GetStyleColorVec4(ImGuiCol_Text); - const ImVec4 colorFalse = ImGui::GetStyleColorVec4(ImGuiCol_WindowBg); + const ImVec4 colorTrue = getColorNonZero(); + const ImVec4 colorFalse = getColorZero(); // Extract R, G, B components const unsigned char rTrue = static_cast(255.f * colorTrue.x); @@ -211,6 +224,24 @@ void DataWidget::showWidget(MyData& data) { *lastCounter = counter; } + + if (ImGui::ColorEdit3(("Color non-zero##" + data.getOwner()->getPathName() + data.getName()).c_str(), (float*)&sofamatrix::imgui::getColorNonZero(), ImGuiColorEditFlags_DisplayRGB) + || + ImGui::ColorEdit3(("Color zero##" + data.getOwner()->getPathName() + data.getName()).c_str(), (float*)&sofamatrix::imgui::getColorZero(), ImGuiColorEditFlags_DisplayRGB)) + { + auto textureID = sofamatrix::imgui::textureID(matrix); + if (textureID.has_value() == false) + return; + + auto imageData = sofamatrix::imgui::imageData(matrix); + if (imageData.has_value() == false) + return; + + auto& textureIDRef = textureID.value(); + auto& imageDataRef = imageData.value(); + + sofamatrix::imgui::updateTexture(matrix, textureIDRef, imageDataRef); + } } else { From 7664c12605c66ac858ab73b3faf8be88cd93c448 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Mon, 27 Jul 2026 13:20:37 +0200 Subject: [PATCH 3/3] button to save matrix --- .../imgui/BaseMatrixImageProxyWidget.cpp | 74 ++++++++++++++++--- 1 file changed, 63 insertions(+), 11 deletions(-) diff --git a/applications/plugins/SofaMatrix/extensions/imgui/src/SofaMatrix/imgui/BaseMatrixImageProxyWidget.cpp b/applications/plugins/SofaMatrix/extensions/imgui/src/SofaMatrix/imgui/BaseMatrixImageProxyWidget.cpp index df515254ebc..5bdcc229aff 100644 --- a/applications/plugins/SofaMatrix/extensions/imgui/src/SofaMatrix/imgui/BaseMatrixImageProxyWidget.cpp +++ b/applications/plugins/SofaMatrix/extensions/imgui/src/SofaMatrix/imgui/BaseMatrixImageProxyWidget.cpp @@ -24,6 +24,10 @@ #include #include #include +#include +#include +#include +#include #include @@ -225,22 +229,70 @@ void DataWidget::showWidget(MyData& data) *lastCounter = counter; } - if (ImGui::ColorEdit3(("Color non-zero##" + data.getOwner()->getPathName() + data.getName()).c_str(), (float*)&sofamatrix::imgui::getColorNonZero(), ImGuiColorEditFlags_DisplayRGB) + if (ImGui::ColorEdit3(("Color non-zero##" + data.getOwner()->getPathName() + data.getName()).c_str(), (float*)&sofamatrix::imgui::getColorNonZero()) || - ImGui::ColorEdit3(("Color zero##" + data.getOwner()->getPathName() + data.getName()).c_str(), (float*)&sofamatrix::imgui::getColorZero(), ImGuiColorEditFlags_DisplayRGB)) + ImGui::ColorEdit3(("Color zero##" + data.getOwner()->getPathName() + data.getName()).c_str(), (float*)&sofamatrix::imgui::getColorZero())) { auto textureID = sofamatrix::imgui::textureID(matrix); - if (textureID.has_value() == false) - return; - - auto imageData = sofamatrix::imgui::imageData(matrix); - if (imageData.has_value() == false) - return; + if (textureID.has_value() == true) + { + auto imageData = sofamatrix::imgui::imageData(matrix); + if (imageData.has_value() == true) + { + auto& textureIDRef = textureID.value(); + auto& imageDataRef = imageData.value(); + + sofamatrix::imgui::updateTexture(matrix, textureIDRef, imageDataRef); + } + } + } - auto& textureIDRef = textureID.value(); - auto& imageDataRef = imageData.value(); + ImGui::NewLine(); + if (ImGui::Button(("Save image##" + data.getOwner()->getPathName() + data.getName()).c_str())) + { + sofa::helper::io::STBImage image; + image.init(matrix->rows(), matrix->cols(), 1, 1, + sofa::helper::io::Image::DataType::UNORM8, sofa::helper::io::Image::ChannelFormat::RGB); - sofamatrix::imgui::updateTexture(matrix, textureIDRef, imageDataRef); + auto textureID = sofamatrix::imgui::textureID(matrix); + if (textureID.has_value() == true) + { + auto imageData = sofamatrix::imgui::imageData(matrix); + if (imageData.has_value() == true) + { + auto& imageDataRef = imageData.value(); + auto& textureIDRef = textureID.value(); + sofamatrix::imgui::updateTexture(matrix, textureIDRef, imageDataRef); + + if (!imageDataRef.empty()) + { + unsigned char* pixels = image.getPixels(); + for (sofa::SignedIndex y = 0; y < matrix->cols(); ++y) + { + for (sofa::SignedIndex x = 0; x < matrix->rows(); ++x) + { + for (std::size_t i = 0; i < 3; ++i) + { + pixels[y * matrix->rows() * 3 + x * 3 + i] = imageDataRef[(matrix->rows() - y) * matrix->rows() * 3 + x * 3 + i]; + } + } + } + const auto filename = sofa::helper::system::FileSystem::append(sofa::helper::Utils::getExecutableDirectory(), "matrix.bmp"); + if (image.save(filename)) + { + msg_info("Matrix") << "Saved matrix file in '" << filename << "'"; + } + else + { + msg_error(data.getOwner()) << "Error while saving matrix to file '" << filename << "'"; + } + } + else + { + msg_error(data.getOwner()) << "Cannot save matrix to file"; + } + } + } } } else