Czi rendering (#10)
* add dimension selector sliders to czi view * version doc & version bump * cosmetic * fix build? * multi-dimension selection enabled in czi view * remove the parameterized reset function of the renderer it is not and is conceptually questionable doc updates & some minor improvements auto-update CZI-view when sliders are moved set initial window size fix windows build and msvc build For reasons I don not comprehend, on Windows, we must include =opencv2/core/mat.hpp= as the very last header in the =CvMatRender.hpp=. If this is at any other position building on Windows, compilation will break w/ all kinds of cryptic errors regarding OpenCV. When building w/ msvc =__PRETTY_FUNCTION__= is not defined. =ILog.hpp= now defines it. This should be revised to only be set when the compiler is msvc. For the time being, it is considered sufficient though.
This commit is contained in:
committed by
Maximilian Kueffner
parent
e60203b57d
commit
1ea83d9d11
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
cmake_minimum_required(VERSION 3.23)
|
cmake_minimum_required(VERSION 3.23)
|
||||||
|
|
||||||
project(pixelarium VERSION 0.0.1)
|
project(pixelarium VERSION 0.0.4)
|
||||||
|
|
||||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||||
set(CXX_STANDARD 20)
|
set(CXX_STANDARD 20)
|
||||||
|
|||||||
@@ -14,4 +14,9 @@ DOXYFILE_ENCODING = UTF-8
|
|||||||
GENERATE_LATEX = NO
|
GENERATE_LATEX = NO
|
||||||
FULL_PATH_NAMES = NO
|
FULL_PATH_NAMES = NO
|
||||||
USE_MDFILE_AS_MAINPAGE = @PROJECT_SOURCE_DIR@/doc/index.md
|
USE_MDFILE_AS_MAINPAGE = @PROJECT_SOURCE_DIR@/doc/index.md
|
||||||
|
|
||||||
|
|
||||||
HTML_EXTRA_STYLESHEET = @AWESOME_CSS_DIR@/doxygen-awesome.css
|
HTML_EXTRA_STYLESHEET = @AWESOME_CSS_DIR@/doxygen-awesome.css
|
||||||
|
GENERATE_TREEVIEW = YES
|
||||||
|
DISABLE_INDEX = NO
|
||||||
|
FULL_SIDEBAR = NO
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# Version History
|
||||||
|
|
||||||
|
| Version | Description |
|
||||||
|
|:-------:|:------------------------------------------------------------------------|
|
||||||
|
| 0.0.4 | Fix MSVC build, some cosmetics, explicit initial window size for images |
|
||||||
|
| 0.0.3 | Fetch subblocks based on the dimension selection sliders |
|
||||||
|
| 0.0.2 | Add Dimension selector sliders to CZI image view |
|
||||||
|
| 0.0.1 | Initiate CZI image view |
|
||||||
|
| 0.0.0 | Initial version |
|
||||||
|
|
||||||
@@ -9,19 +9,33 @@
|
|||||||
|
|
||||||
namespace pixelarium::application
|
namespace pixelarium::application
|
||||||
{
|
{
|
||||||
|
/// @brief Base class providing scaffolding with GLFW and some default
|
||||||
|
/// implementations that can be extended and/or overridden by consumers
|
||||||
class AppGLFW
|
class AppGLFW
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit AppGLFW(const utils::log::ILog& log) : logger_(log) { this->InitMainWindow(); }
|
explicit AppGLFW(const utils::log::ILog& log) : logger_(log) { this->InitMainWindow(); }
|
||||||
|
|
||||||
|
/// @brief Start the main render loop
|
||||||
void Start() { this->RunLoop(); }
|
void Start() { this->RunLoop(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
/// @brief Function implementing the first column of the menu bar (e.g. "Menu")
|
||||||
virtual void MenuBarOptionsColumn1() {}
|
virtual void MenuBarOptionsColumn1() {}
|
||||||
|
|
||||||
|
/// @brief Function implementing the second column of the menu bar (e.g. "File")
|
||||||
virtual void MenuBarOptionsColumn2() {}
|
virtual void MenuBarOptionsColumn2() {}
|
||||||
|
|
||||||
|
/// @brief Function implementing the third column of the menu bar (e.g. "Options")
|
||||||
virtual void MenuBarOptionsColumn3() {}
|
virtual void MenuBarOptionsColumn3() {}
|
||||||
|
|
||||||
|
/// @brief Function implementing the fourth column of the menu bar (e.g. "More")
|
||||||
virtual void MenuBarOptionsColumn4() {}
|
virtual void MenuBarOptionsColumn4() {}
|
||||||
|
|
||||||
|
/// @brief Function implementing the first column of the menu bar (e.g. "Help")
|
||||||
virtual void MenuBarOptionsColumn5() {}
|
virtual void MenuBarOptionsColumn5() {}
|
||||||
|
|
||||||
|
/// @brief Main function that gets called within the render loop.
|
||||||
virtual void Run() {}
|
virtual void Run() {}
|
||||||
|
|
||||||
const utils::log::ILog& logger_;
|
const utils::log::ILog& logger_;
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ void pixelarium::ui::DefaultApp::LoadImage()
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
pool_.SetResource(PixelariumImageFactory::CreateImage(p));
|
pool_.SetResource(PixelariumImageFactory::CreateImage(p, logger_));
|
||||||
}
|
}
|
||||||
catch (pixelarium::resources::empty_resource_exception& e)
|
catch (pixelarium::resources::empty_resource_exception& e)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,6 +11,9 @@
|
|||||||
|
|
||||||
namespace pixelarium::ui
|
namespace pixelarium::ui
|
||||||
{
|
{
|
||||||
|
/// @brief Default implementation of AppGLFW.
|
||||||
|
/// This can either be used as is, as an example or as a base class
|
||||||
|
/// providing some defaults for a more custom implementation.
|
||||||
class DefaultApp : public application::AppGLFW
|
class DefaultApp : public application::AppGLFW
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -24,9 +24,11 @@ add_library(${IMAGELIBLIBNAME}
|
|||||||
|
|
||||||
target_link_libraries(${IMAGELIBLIBNAME}
|
target_link_libraries(${IMAGELIBLIBNAME}
|
||||||
PUBLIC ${OpenCV_LIBS}
|
PUBLIC ${OpenCV_LIBS}
|
||||||
|
PUBLIC pixelariumutilslib
|
||||||
PRIVATE libCZIStatic)
|
PRIVATE libCZIStatic)
|
||||||
|
|
||||||
|
|
||||||
target_include_directories(${IMAGELIBLIBNAME}
|
target_include_directories(${IMAGELIBLIBNAME}
|
||||||
|
PRIVATE ${CMAKE_SOURCE_DIR}/lib
|
||||||
PUBLIC ${OpenCV_INCLUDE_DIRS}
|
PUBLIC ${OpenCV_INCLUDE_DIRS}
|
||||||
PUBLIC ${LIBCZI_INCLUDE_DIR})
|
PUBLIC ${LIBCZI_INCLUDE_DIR})
|
||||||
|
|||||||
@@ -46,15 +46,16 @@ class IPixelariumImage
|
|||||||
virtual std::unique_ptr<cv::Mat> TryGetImage() = 0;
|
virtual std::unique_ptr<cv::Mat> TryGetImage() = 0;
|
||||||
|
|
||||||
/// @brief Attempts to retrieve the image.
|
/// @brief Attempts to retrieve the image.
|
||||||
|
/// @param query The query object defining the images to retrieve.///
|
||||||
/// @return A unique pointer to a Mat object containing the image data,
|
/// @return A unique pointer to a Mat object containing the image data,
|
||||||
/// or nullptr if the image is not found or cannot be retrieved.
|
/// or nullptr if the image is not found or cannot be retrieved.
|
||||||
virtual std::unique_ptr<cv::Mat> TryGetImage(const IImageQuery&) = 0;
|
virtual std::unique_ptr<cv::Mat> TryGetImage(const IImageQuery& query) = 0;
|
||||||
|
|
||||||
/// @brief Attempts to retrieve a collection of images based on a query.
|
/// @brief Attempts to retrieve a collection of images based on a query.
|
||||||
/// @param query The query object defining the images to retrieve.
|
/// @param query The query object defining the images to retrieve.
|
||||||
/// @return A vector of unique pointers to cv::Mat objects. Each element is an image.
|
/// @return A vector of unique pointers to cv::Mat objects. Each element is an image.
|
||||||
/// Returns an empty vector if no images are found or if an error occurs.
|
/// Returns an empty vector if no images are found or if an error occurs.
|
||||||
virtual std::vector<std::unique_ptr<cv::Mat>> TryGetImages(const IImageQuery&) = 0;
|
virtual std::vector<std::unique_ptr<cv::Mat>> TryGetImages(const IImageQuery& query) = 0;
|
||||||
|
|
||||||
/// @brief Checks if the image is empty.
|
/// @brief Checks if the image is empty.
|
||||||
/// @return true if the image is empty, false otherwise.
|
/// @return true if the image is empty, false otherwise.
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#include "PixelariumImageFactory.hpp"
|
#include "PixelariumImageFactory.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@@ -10,7 +9,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/*static*/ std::unique_ptr<pixelarium::imaging::IPixelariumImage>
|
/*static*/ std::unique_ptr<pixelarium::imaging::IPixelariumImage>
|
||||||
pixelarium::imaging::PixelariumImageFactory::CreateImage(const std::string& uri)
|
pixelarium::imaging::PixelariumImageFactory::CreateImage(const std::string& uri, const Log& log)
|
||||||
{
|
{
|
||||||
const auto res{std::filesystem::path(uri)};
|
const auto res{std::filesystem::path(uri)};
|
||||||
const auto target_type{ExtensionToType(res.extension().string())};
|
const auto target_type{ExtensionToType(res.extension().string())};
|
||||||
@@ -30,7 +29,7 @@ pixelarium::imaging::PixelariumImageFactory::CreateImage(const std::string& uri)
|
|||||||
return std::make_unique<PixelariumJpg>(uri);
|
return std::make_unique<PixelariumJpg>(uri);
|
||||||
break;
|
break;
|
||||||
case ImageFileType::CZI:
|
case ImageFileType::CZI:
|
||||||
return std::make_unique<PixelariumCzi>(uri);
|
return std::make_unique<PixelariumCzi>(uri, log);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "IPixelariumImage.hpp"
|
#include "IPixelariumImage.hpp"
|
||||||
|
#include "utilities/ILog.hpp"
|
||||||
namespace pixelarium::imaging
|
namespace pixelarium::imaging
|
||||||
{
|
{
|
||||||
constexpr pixelarium::imaging::ImageFileType ExtensionToType(const std::string& extension)
|
constexpr pixelarium::imaging::ImageFileType ExtensionToType(const std::string& extension)
|
||||||
@@ -26,9 +27,12 @@ constexpr pixelarium::imaging::ImageFileType ExtensionToType(const std::string&
|
|||||||
return pixelarium::imaging::ImageFileType::UNKNOWN;
|
return pixelarium::imaging::ImageFileType::UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief Factory for instantiating implementations of IPixelariumImage based on the given file type.
|
||||||
class PixelariumImageFactory
|
class PixelariumImageFactory
|
||||||
{
|
{
|
||||||
|
using Log = utils::log::ILog;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::unique_ptr<IPixelariumImage> CreateImage(const std::string& uri);
|
static std::unique_ptr<IPixelariumImage> CreateImage(const std::string& uri, const Log& log);
|
||||||
};
|
};
|
||||||
} // namespace pixelarium::imaging
|
} // namespace pixelarium::imaging
|
||||||
|
|||||||
@@ -1,58 +1,95 @@
|
|||||||
#include "PixelariumCzi.hpp"
|
#include "PixelariumCzi.hpp"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <format>
|
||||||
|
#include <memory>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "libCZI.h"
|
#include "libCZI.h"
|
||||||
|
#include "utilities/ILog.hpp"
|
||||||
|
|
||||||
pixelarium::imaging::PixelariumCzi::PixelariumCzi(const std::string& uri)
|
bool comp_blockinfo_params(const pixelarium::imaging::CziParams& params, const libCZI::SubBlockInfo& info)
|
||||||
{
|
{
|
||||||
if (!std::filesystem::exists(uri))
|
bool res{true};
|
||||||
|
|
||||||
|
info.coordinate.EnumValidDimensions(
|
||||||
|
[&](libCZI::DimensionIndex dim, int start) -> bool
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Render file not found.");
|
if (params.dimension_map.at(dim) == start)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->is_empty_ = false;
|
res &= false;
|
||||||
this->uri_ = std::filesystem::path(uri);
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
auto stream = libCZI::CreateStreamFromFile(this->uri_.wstring().c_str());
|
return res;
|
||||||
this->czi_reader_ = libCZI::CreateCZIReader();
|
|
||||||
this->czi_reader_->Open(stream);
|
|
||||||
this->image_statistics_ = this->czi_reader_->GetStatistics();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<cv::Mat> CZISubBlockToCvMat(std::shared_ptr<libCZI::IBitmapData> bitmap, libCZI::PixelType pixeltype)
|
|
||||||
|
constexpr int try_get_index_match(const pixelarium::imaging::CziParams& params, libCZI::ICZIReader& reader)
|
||||||
|
{
|
||||||
|
int index{-1};
|
||||||
|
reader.EnumerateSubBlocks(
|
||||||
|
[&](int idx, const libCZI::SubBlockInfo& info) -> bool
|
||||||
|
{
|
||||||
|
if (comp_blockinfo_params(params, info))
|
||||||
|
{
|
||||||
|
index = idx;
|
||||||
|
// returning false will stop the enumeration
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<cv::Mat> CZISubBlockToCvMat(std::shared_ptr<libCZI::IBitmapData> bitmap, libCZI::PixelType pixeltype,
|
||||||
|
const pixelarium::utils::log::ILog& log)
|
||||||
{
|
{
|
||||||
size_t pixel_size{0};
|
size_t pixel_size{0};
|
||||||
int target_type;
|
int target_type;
|
||||||
|
std::pair<std::string, std::string> pixel_pair;
|
||||||
|
|
||||||
switch (pixeltype)
|
switch (pixeltype)
|
||||||
{
|
{
|
||||||
case libCZI::PixelType::Gray8:
|
case libCZI::PixelType::Gray8:
|
||||||
|
pixel_pair.first = "Gray8";
|
||||||
|
pixel_pair.second = "CV_8U";
|
||||||
pixel_size = 1;
|
pixel_size = 1;
|
||||||
target_type = CV_8U;
|
target_type = CV_8U;
|
||||||
break;
|
break;
|
||||||
case libCZI::PixelType::Gray16:
|
case libCZI::PixelType::Gray16:
|
||||||
|
pixel_pair.first = "Gray16";
|
||||||
|
pixel_pair.second = "CV_16U";
|
||||||
pixel_size = 2;
|
pixel_size = 2;
|
||||||
target_type = CV_16U;
|
target_type = CV_16U;
|
||||||
break;
|
break;
|
||||||
case libCZI::PixelType::Bgr24:
|
case libCZI::PixelType::Bgr24:
|
||||||
|
pixel_pair.first = "Bgr24";
|
||||||
|
pixel_pair.second = "CV_8UC3";
|
||||||
pixel_size = 3;
|
pixel_size = 3;
|
||||||
target_type = CV_8UC3;
|
target_type = CV_8UC3;
|
||||||
break;
|
break;
|
||||||
case libCZI::PixelType::Bgra32:
|
case libCZI::PixelType::Bgra32:
|
||||||
|
pixel_pair.first = "Bgra32";
|
||||||
|
pixel_pair.second = "CV_8CU4";
|
||||||
target_type = CV_8UC4;
|
target_type = CV_8UC4;
|
||||||
case libCZI::PixelType::Gray32:
|
case libCZI::PixelType::Gray32:
|
||||||
|
pixel_pair.first = "Gray32";
|
||||||
|
pixel_pair.second = "CV_32S";
|
||||||
target_type = CV_32S;
|
target_type = CV_32S;
|
||||||
case libCZI::PixelType::Gray32Float:
|
case libCZI::PixelType::Gray32Float:
|
||||||
|
pixel_pair.first = "Gray32Float";
|
||||||
|
pixel_pair.second = "CV_32F";
|
||||||
target_type = CV_32F;
|
target_type = CV_32F;
|
||||||
pixel_size = 4;
|
pixel_size = 4;
|
||||||
break;
|
break;
|
||||||
// case libCZI::PixelType::Gray64ComplexFloat:
|
|
||||||
// case libCZI::PixelType::Gray64Float:
|
|
||||||
// target_type =
|
|
||||||
// pixel_size = 8;
|
|
||||||
// break;
|
|
||||||
default:
|
default:
|
||||||
pixel_size = -1;
|
pixel_size = -1;
|
||||||
break;
|
break;
|
||||||
@@ -60,6 +97,9 @@ std::unique_ptr<cv::Mat> CZISubBlockToCvMat(std::shared_ptr<libCZI::IBitmapData>
|
|||||||
|
|
||||||
if (pixel_size < 0) return nullptr;
|
if (pixel_size < 0) return nullptr;
|
||||||
|
|
||||||
|
log.Info(std::format("{}: source pixel type {}, target cv pixel type {}, pixel size {}", __PRETTY_FUNCTION__,
|
||||||
|
pixel_pair.first, pixel_pair.second, pixel_size));
|
||||||
|
|
||||||
size_t height{bitmap->GetHeight()};
|
size_t height{bitmap->GetHeight()};
|
||||||
size_t width{bitmap->GetWidth()};
|
size_t width{bitmap->GetWidth()};
|
||||||
auto fill_mat = std::make_unique<cv::Mat>(height, width, target_type);
|
auto fill_mat = std::make_unique<cv::Mat>(height, width, target_type);
|
||||||
@@ -86,6 +126,9 @@ std::unique_ptr<cv::Mat> CZISubBlockToCvMat(std::shared_ptr<libCZI::IBitmapData>
|
|||||||
target_row[3 * w + 1] = source_row[3 * w + 1];
|
target_row[3 * w + 1] = source_row[3 * w + 1];
|
||||||
target_row[3 * w + 2] = source_row[3 * w + 2];
|
target_row[3 * w + 2] = source_row[3 * w + 2];
|
||||||
break;
|
break;
|
||||||
|
case 4:
|
||||||
|
reinterpret_cast<std::int32_t*>(target_row)[w] = reinterpret_cast<std::int32_t*>(source_row)[w];
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("Unknown pixel type requested!");
|
throw std::runtime_error("Unknown pixel type requested!");
|
||||||
break;
|
break;
|
||||||
@@ -97,11 +140,48 @@ std::unique_ptr<cv::Mat> CZISubBlockToCvMat(std::shared_ptr<libCZI::IBitmapData>
|
|||||||
return fill_mat;
|
return fill_mat;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<cv::Mat> pixelarium::imaging::PixelariumCzi::TryGetImage()
|
std::unique_ptr<cv::Mat> pixelarium::imaging::PixelariumCzi::SubblockToCvMat(int index)
|
||||||
{
|
{
|
||||||
auto block = this->czi_reader_->ReadSubBlock(0);
|
log_.Info(std::format("{}: constructing bitmap with index {}", __PRETTY_FUNCTION__, index));
|
||||||
|
auto block = this->czi_reader_->ReadSubBlock(index);
|
||||||
auto bitmap = block->CreateBitmap();
|
auto bitmap = block->CreateBitmap();
|
||||||
auto res = CZISubBlockToCvMat(bitmap, block->GetSubBlockInfo().pixelType);
|
return CZISubBlockToCvMat(bitmap, block->GetSubBlockInfo().pixelType, log_);
|
||||||
|
}
|
||||||
return res;
|
|
||||||
|
pixelarium::imaging::PixelariumCzi::PixelariumCzi(const std::string& uri, const Log& log) : log_(log)
|
||||||
|
{
|
||||||
|
if (!std::filesystem::exists(uri))
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Render file not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
this->is_empty_ = false;
|
||||||
|
this->uri_ = std::filesystem::path(uri);
|
||||||
|
|
||||||
|
auto stream = libCZI::CreateStreamFromFile(this->uri_.wstring().c_str());
|
||||||
|
this->czi_reader_ = libCZI::CreateCZIReader();
|
||||||
|
this->czi_reader_->Open(stream);
|
||||||
|
this->image_statistics_ = this->czi_reader_->GetStatistics();
|
||||||
|
|
||||||
|
this->image_statistics_.dimBounds.EnumValidDimensions(
|
||||||
|
[&](libCZI::DimensionIndex dim, int start, int) -> bool
|
||||||
|
{
|
||||||
|
this->dimension_map_[dim] = start;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<cv::Mat> pixelarium::imaging::PixelariumCzi::TryGetImage() { return SubblockToCvMat(0); }
|
||||||
|
|
||||||
|
std::unique_ptr<cv::Mat> pixelarium::imaging::PixelariumCzi::TryGetImage(const IImageQuery& query)
|
||||||
|
{
|
||||||
|
const auto czi_query = static_cast<const CziParams&>(query);
|
||||||
|
int index = try_get_index_match(czi_query, *this->czi_reader_);
|
||||||
|
|
||||||
|
if (index < 0)
|
||||||
|
{
|
||||||
|
return SubblockToCvMat(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SubblockToCvMat(index);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,19 +4,25 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "../IPixelariumImage.hpp"
|
#include "../IPixelariumImage.hpp"
|
||||||
|
#include "utilities/ILog.hpp"
|
||||||
#include "libCZI.h"
|
#include "libCZI.h"
|
||||||
|
|
||||||
namespace pixelarium::imaging
|
namespace pixelarium::imaging
|
||||||
{
|
{
|
||||||
|
/// @brief An implementation of IImageQuery to work on CZI images.
|
||||||
|
/// @note Check the documentation here https://zeiss.github.io/libczi/pages/mainpage.html#czi-in-a-nutshell
|
||||||
struct CziParams : public IImageQuery
|
struct CziParams : public IImageQuery
|
||||||
{
|
{
|
||||||
|
/// @brief A map providing the start coordinate for each dimension in the CZI
|
||||||
|
std::unordered_map<libCZI::DimensionIndex, int> dimension_map;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// @brief Implements support for .czi-images in the realm of IPixelariumImage
|
||||||
class PixelariumCzi : public IPixelariumImage
|
class PixelariumCzi : public IPixelariumImage
|
||||||
{
|
{
|
||||||
|
using Log = pixelarium::utils::log::ILog;
|
||||||
public:
|
public:
|
||||||
explicit PixelariumCzi(const std::string& uri);
|
explicit PixelariumCzi(const std::string& uri, const Log& log);
|
||||||
~PixelariumCzi()
|
~PixelariumCzi()
|
||||||
{
|
{
|
||||||
if (this->czi_reader_)
|
if (this->czi_reader_)
|
||||||
@@ -27,11 +33,7 @@ class PixelariumCzi : public IPixelariumImage
|
|||||||
public:
|
public:
|
||||||
std::unique_ptr<cv::Mat> TryGetImage() override;
|
std::unique_ptr<cv::Mat> TryGetImage() override;
|
||||||
|
|
||||||
std::unique_ptr<cv::Mat> TryGetImage(const IImageQuery&) override
|
std::unique_ptr<cv::Mat> TryGetImage(const IImageQuery&) override;
|
||||||
{
|
|
||||||
// ToDo: proper error
|
|
||||||
throw std::runtime_error("Not implemented.");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::unique_ptr<cv::Mat>> TryGetImages(const IImageQuery&) override
|
std::vector<std::unique_ptr<cv::Mat>> TryGetImages(const IImageQuery&) override
|
||||||
{
|
{
|
||||||
@@ -46,6 +48,9 @@ class PixelariumCzi : public IPixelariumImage
|
|||||||
public:
|
public:
|
||||||
const static ImageFileType type_{ImageFileType::CZI};
|
const static ImageFileType type_{ImageFileType::CZI};
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<cv::Mat> SubblockToCvMat(int index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// this should be set by each image getter
|
// this should be set by each image getter
|
||||||
// after a new cv::Mat could be instantiated
|
// after a new cv::Mat could be instantiated
|
||||||
@@ -54,5 +59,9 @@ class PixelariumCzi : public IPixelariumImage
|
|||||||
libCZI::SubBlockStatistics image_statistics_;
|
libCZI::SubBlockStatistics image_statistics_;
|
||||||
|
|
||||||
std::shared_ptr<libCZI::ICZIReader> czi_reader_;
|
std::shared_ptr<libCZI::ICZIReader> czi_reader_;
|
||||||
|
|
||||||
|
std::unordered_map<libCZI::DimensionIndex, int> dimension_map_;
|
||||||
|
|
||||||
|
const Log& log_;
|
||||||
};
|
};
|
||||||
} // namespace pixelarium::imaging
|
} // namespace pixelarium::imaging
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
namespace pixelarium::imaging
|
namespace pixelarium::imaging
|
||||||
{
|
{
|
||||||
|
/// @brief Implements support for .jpg-images in the realm of IPixelariumImage
|
||||||
class PixelariumJpg : public IPixelariumImage
|
class PixelariumJpg : public IPixelariumImage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
namespace pixelarium::imaging
|
namespace pixelarium::imaging
|
||||||
{
|
{
|
||||||
|
/// @brief Implements support for .png-images in the realm of IPixelariumImage
|
||||||
class PixelariumPng : public IPixelariumImage
|
class PixelariumPng : public IPixelariumImage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
#include "CvMatRender.hpp"
|
#include "CvMatRender.hpp"
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <opencv2/core/mat.hpp>
|
#include <opencv2/core/mat.hpp>
|
||||||
#include <opencv2/imgproc.hpp>
|
#include <opencv2/imgproc.hpp>
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
#include "imaging/IPixelariumImage.hpp"
|
#include "imaging/IPixelariumImage.hpp"
|
||||||
|
|
||||||
@@ -11,7 +9,7 @@ using namespace pixelarium::imaging;
|
|||||||
|
|
||||||
/// @brief Constructor for the CvMatRender class.
|
/// @brief Constructor for the CvMatRender class.
|
||||||
/// @param img A shared pointer to the PixelariumImage to be rendered.
|
/// @param img A shared pointer to the PixelariumImage to be rendered.
|
||||||
pixelarium::render::CvMatRender::CvMatRender(std::shared_ptr<pixelarium::imaging::IPixelariumImage>& img) : base_(img), texture_(0)
|
pixelarium::render::CvMatRender::CvMatRender(const cv::Mat& img) : base_(img), texture_(0)
|
||||||
{
|
{
|
||||||
// storing a copy of the to-be-rendered image
|
// storing a copy of the to-be-rendered image
|
||||||
// because it will be resized and filtered eventually which we absolutely
|
// because it will be resized and filtered eventually which we absolutely
|
||||||
@@ -31,15 +29,6 @@ pixelarium::render::CvMatRender::~CvMatRender()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Resets the render image with a new PixelariumImage.
|
|
||||||
/// @param img A shared pointer to the new PixelariumImage.
|
|
||||||
void pixelarium::render::CvMatRender::ResetRenderImage(std::shared_ptr<pixelarium::imaging::IPixelariumImage>& img)
|
|
||||||
{
|
|
||||||
this->base_ = img;
|
|
||||||
this->ResetRenderImage();
|
|
||||||
cv::cvtColor(this->img_, this->img_, cv::COLOR_BGR2RGBA);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Uploads the current image data to an OpenGL texture.
|
/// @brief Uploads the current image data to an OpenGL texture.
|
||||||
/// @return The ID of the uploaded OpenGL texture.
|
/// @return The ID of the uploaded OpenGL texture.
|
||||||
/// @throws std::runtime_error if the image data is empty or if there is an OpenGL error.
|
/// @throws std::runtime_error if the image data is empty or if there is an OpenGL error.
|
||||||
@@ -103,11 +92,7 @@ GLuint pixelarium::render::CvMatRender::Render() { return this->uploadTexture();
|
|||||||
/// @return The ID of the OpenGL texture.
|
/// @return The ID of the OpenGL texture.
|
||||||
GLuint pixelarium::render::CvMatRender::Render(float factor)
|
GLuint pixelarium::render::CvMatRender::Render(float factor)
|
||||||
{
|
{
|
||||||
auto res_val {this->base_->TryGetImage()};
|
cv::resize(this->base_, this->img_, cv::Size(0, 0), factor, factor, cv::INTER_LINEAR_EXACT);
|
||||||
if (res_val)
|
|
||||||
{
|
|
||||||
cv::resize(*res_val, this->img_, cv::Size(0, 0), factor, factor, cv::INTER_LINEAR_EXACT);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this->uploadTexture();
|
return this->uploadTexture();
|
||||||
}
|
}
|
||||||
@@ -118,14 +103,7 @@ GLuint pixelarium::render::CvMatRender::Render(float factor)
|
|||||||
/// @return The ID of the OpenGL texture.
|
/// @return The ID of the OpenGL texture.
|
||||||
GLuint pixelarium::render::CvMatRender::Render(size_t width, size_t height)
|
GLuint pixelarium::render::CvMatRender::Render(size_t width, size_t height)
|
||||||
{
|
{
|
||||||
auto res_val {this->base_->TryGetImage()};
|
const auto sz{this->base_.size()};
|
||||||
|
|
||||||
if (!res_val)
|
|
||||||
{
|
|
||||||
return this->Render(1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto sz{res_val->size()};
|
|
||||||
|
|
||||||
const auto get_factor = [](auto opt1, auto opt2) -> float { return opt1 < opt2 ? opt1 : opt2; };
|
const auto get_factor = [](auto opt1, auto opt2) -> float { return opt1 < opt2 ? opt1 : opt2; };
|
||||||
|
|
||||||
@@ -136,18 +114,6 @@ GLuint pixelarium::render::CvMatRender::Render(size_t width, size_t height)
|
|||||||
|
|
||||||
void pixelarium::render::CvMatRender::ResetRenderImage()
|
void pixelarium::render::CvMatRender::ResetRenderImage()
|
||||||
{
|
{
|
||||||
if (this->base_ == nullptr)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto root_res = this->base_->TryGetImage();
|
|
||||||
|
|
||||||
if (!root_res)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// we copy here
|
// we copy here
|
||||||
this->img_ = root_res->clone();
|
this->img_ = this->base_.clone();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
// windows.h must come before GL/GL.h here.
|
// windows.h must come before GL/GL.h here.
|
||||||
// clang format would change this, effectively rendering the build broken.
|
// clang format would change this, effectively rendering the build broken.
|
||||||
// clang-format off
|
// clang-format off
|
||||||
#include <memory>
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <GL/GL.h>
|
#include <GL/GL.h>
|
||||||
@@ -13,11 +12,12 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <GLFW/glfw3.h> // Will drag system OpenGL headers
|
#include <GLFW/glfw3.h> // Will drag system OpenGL headers
|
||||||
#endif
|
#endif
|
||||||
#include "imaging/IPixelariumImage.hpp"
|
#include <opencv2/core/mat.hpp>
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
namespace pixelarium::render
|
namespace pixelarium::render
|
||||||
{
|
{
|
||||||
|
/// @brief Renders cv::Mat bitmaps as OpenGL textures.
|
||||||
class CvMatRender
|
class CvMatRender
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -26,25 +26,24 @@ class CvMatRender
|
|||||||
// get removed in the future)
|
// get removed in the future)
|
||||||
// as the using AppGLFW constructs it empty as a member
|
// as the using AppGLFW constructs it empty as a member
|
||||||
// when coming to life.
|
// when coming to life.
|
||||||
CvMatRender() = default;
|
// CvMatRender() = default;
|
||||||
CvMatRender(CvMatRender&) = delete;
|
CvMatRender(CvMatRender&) = delete;
|
||||||
CvMatRender(const CvMatRender&) = delete;
|
CvMatRender(const CvMatRender&) = delete;
|
||||||
CvMatRender(CvMatRender&&) = delete;
|
CvMatRender(CvMatRender&&) = delete;
|
||||||
CvMatRender& operator=(CvMatRender&) = default;
|
CvMatRender& operator=(CvMatRender&) = delete;
|
||||||
CvMatRender& operator=(CvMatRender&& other) = default;
|
CvMatRender& operator=(CvMatRender&& other) = delete;
|
||||||
~CvMatRender();
|
~CvMatRender();
|
||||||
explicit CvMatRender(std::shared_ptr<pixelarium::imaging::IPixelariumImage>& img);
|
explicit CvMatRender(const cv::Mat& img);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GLuint Render();
|
GLuint Render();
|
||||||
GLuint Render(float factor);
|
GLuint Render(float factor);
|
||||||
GLuint Render(size_t width, size_t height);
|
GLuint Render(size_t width, size_t height);
|
||||||
void ResetRenderImage();
|
void ResetRenderImage();
|
||||||
void ResetRenderImage(std::shared_ptr<pixelarium::imaging::IPixelariumImage>& img);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cv::Mat img_;
|
cv::Mat img_;
|
||||||
std::shared_ptr<pixelarium::imaging::IPixelariumImage> base_;
|
const cv::Mat& base_;
|
||||||
GLuint texture_;
|
GLuint texture_;
|
||||||
|
|
||||||
GLuint uploadTexture();
|
GLuint uploadTexture();
|
||||||
|
|||||||
@@ -3,10 +3,11 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "imaging/IPixelariumImage.hpp"
|
#include "imaging/IPixelariumImage.hpp"
|
||||||
#include "rendering/CvMatRender.hpp"
|
#include "imgui.h"
|
||||||
|
|
||||||
namespace pixelarium::render
|
namespace pixelarium::render
|
||||||
{
|
{
|
||||||
|
/// @brief An interface defining the contract on views to dedicated implementations of IPixelariumImage
|
||||||
class IPixelariumImageView
|
class IPixelariumImageView
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -17,11 +18,14 @@ class IPixelariumImageView
|
|||||||
public:
|
public:
|
||||||
virtual const bool* GetStatus() const noexcept { return &this->open_p; }
|
virtual const bool* GetStatus() const noexcept { return &this->open_p; }
|
||||||
virtual void ForceUpdate() noexcept { this->is_dirty_ = true; }
|
virtual void ForceUpdate() noexcept { this->is_dirty_ = true; }
|
||||||
|
virtual void SetInitialSize(float width = 700.0f, float height = 700.0f)
|
||||||
|
{
|
||||||
|
ImGui::SetNextWindowSize({width, height});
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::shared_ptr<imaging::IPixelariumImage> img_{};
|
std::shared_ptr<imaging::IPixelariumImage> img_{};
|
||||||
std::unique_ptr<cv::Mat> cached_image_{};
|
std::unique_ptr<cv::Mat> cached_image_{};
|
||||||
render::CvMatRender render_;
|
|
||||||
bool open_p{true};
|
bool open_p{true};
|
||||||
bool is_dirty_{true};
|
bool is_dirty_{true};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#include "ImageViewFactory.hpp"
|
#include "ImageViewFactory.hpp"
|
||||||
|
|
||||||
|
#include <format>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "imaging/PixelariumImageFactory.hpp"
|
#include "imaging/PixelariumImageFactory.hpp"
|
||||||
#include "rendering/IPixelariumImageView.hpp"
|
#include "rendering/IPixelariumImageView.hpp"
|
||||||
#include "rendering/PixelariumImageViewCzi.hpp"
|
#include "rendering/PixelariumImageViewCzi.hpp"
|
||||||
@@ -8,9 +10,10 @@
|
|||||||
|
|
||||||
/// @brief Creates a PixelariumImageView from a resource image.
|
/// @brief Creates a PixelariumImageView from a resource image.
|
||||||
/// @param image_id The ID of the image resource to render.
|
/// @param image_id The ID of the image resource to render.
|
||||||
/// @return A unique pointer to the PixelariumImageView, or nullptr if the image resource is not found or is empty. The image data is copied.
|
/// @return A unique pointer to the PixelariumImageView, or nullptr if the image resource is not found or is empty. The
|
||||||
|
/// image data is copied.
|
||||||
std::unique_ptr<pixelarium::render::IPixelariumImageView> pixelarium::render::ImageViewFactory::RenderImage(
|
std::unique_ptr<pixelarium::render::IPixelariumImageView> pixelarium::render::ImageViewFactory::RenderImage(
|
||||||
size_t image_id)
|
resources::ResourceKey image_id)
|
||||||
{
|
{
|
||||||
auto res{this->image_pool_.GetResource(image_id)};
|
auto res{this->image_pool_.GetResource(image_id)};
|
||||||
|
|
||||||
@@ -35,15 +38,14 @@ std::unique_ptr<pixelarium::render::IPixelariumImageView> pixelarium::render::Im
|
|||||||
return {};
|
return {};
|
||||||
case imaging::ImageFileType::PNG:
|
case imaging::ImageFileType::PNG:
|
||||||
case imaging::ImageFileType::JPG:
|
case imaging::ImageFileType::JPG:
|
||||||
log_.Info("Creating a Default View");
|
log_.Info(std::format("{}: Creating a Default View", __PRETTY_FUNCTION__));
|
||||||
// beware: here we copy the actual image resource over to the new image
|
// beware: here we copy the actual image resource over to the new image
|
||||||
return std::make_unique<PixelariumImageViewDefault>(img);
|
return std::make_unique<PixelariumImageViewDefault>(img);
|
||||||
case imaging::ImageFileType::CZI:
|
case imaging::ImageFileType::CZI:
|
||||||
log_.Info("{}: Creating a CZI View");
|
log_.Info(std::format("{}: Creating a CZI View", __PRETTY_FUNCTION__));
|
||||||
// beware: here we copy the actual image resource over to the new image
|
// beware: here we copy the actual image resource over to the new image
|
||||||
return std::make_unique<PixelariumImageViewCzi>(img);
|
return std::make_unique<PixelariumImageViewCzi>(img, log_);
|
||||||
default:
|
default:
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "utilities/ILog.hpp"
|
#include "utilities/ILog.hpp"
|
||||||
namespace pixelarium::render
|
namespace pixelarium::render
|
||||||
{
|
{
|
||||||
|
/// @brief Factory for instantiating matching views to different implementations of IPixelariumImage.
|
||||||
class ImageViewFactory
|
class ImageViewFactory
|
||||||
{
|
{
|
||||||
using Image = imaging::IPixelariumImage;
|
using Image = imaging::IPixelariumImage;
|
||||||
@@ -15,7 +16,7 @@ class ImageViewFactory
|
|||||||
public:
|
public:
|
||||||
explicit ImageViewFactory(Pool& pool, const Log& log) : image_pool_(pool), log_(log) {}
|
explicit ImageViewFactory(Pool& pool, const Log& log) : image_pool_(pool), log_(log) {}
|
||||||
|
|
||||||
std::unique_ptr<IPixelariumImageView> RenderImage(size_t id);
|
std::unique_ptr<IPixelariumImageView> RenderImage(resources::ResourceKey id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Pool& image_pool_;
|
Pool& image_pool_;
|
||||||
|
|||||||
@@ -1,11 +1,31 @@
|
|||||||
#include "PixelariumImageViewCzi.hpp"
|
#include "PixelariumImageViewCzi.hpp"
|
||||||
|
|
||||||
#include <format>
|
#include <format>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "RenderHelpers.hpp"
|
#include "RenderHelpers.hpp"
|
||||||
#include "imaging/IPixelariumImage.hpp"
|
#include "imaging/IPixelariumImage.hpp"
|
||||||
#include "imaging/impl/PixelariumCzi.hpp"
|
#include "imaging/impl/PixelariumCzi.hpp"
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
|
#include "rendering/CvMatRender.hpp"
|
||||||
|
|
||||||
|
pixelarium::render::PixelariumImageViewCzi::PixelariumImageViewCzi(std::shared_ptr<Image> img, const Log& log)
|
||||||
|
: log_(log), render_(std::make_unique<CvMatRender>(*img->TryGetImage()))
|
||||||
|
{
|
||||||
|
img_ = img;
|
||||||
|
auto czi_img = std::static_pointer_cast<imaging::PixelariumCzi>(this->img_);
|
||||||
|
|
||||||
|
auto stats = czi_img->GetStatistics();
|
||||||
|
stats.dimBounds.EnumValidDimensions(
|
||||||
|
[&](libCZI::DimensionIndex dim, int start, int) -> bool
|
||||||
|
{
|
||||||
|
this->dimension_map_[dim] = start;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
this->SetInitialSize();
|
||||||
|
log_.Info(std::format("{}: dimension map size: {}", __PRETTY_FUNCTION__, dimension_map_.size()));
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief Displays the image in an ImGui window.
|
/// @brief Displays the image in an ImGui window.
|
||||||
///
|
///
|
||||||
@@ -20,7 +40,14 @@ void pixelarium::render::PixelariumImageViewCzi::ShowImage()
|
|||||||
|
|
||||||
if (!this->cached_image_ || this->is_dirty_)
|
if (!this->cached_image_ || this->is_dirty_)
|
||||||
{
|
{
|
||||||
this->cached_image_ = this->img_->TryGetImage();
|
log_.Info(std::format("{}: refreshing image.", __PRETTY_FUNCTION__));
|
||||||
|
imaging::CziParams params;
|
||||||
|
params.dimension_map = this->dimension_map_;
|
||||||
|
this->cached_image_ = this->img_->TryGetImage(params);
|
||||||
|
// Resetting the image while the renderer is possibly accessing the
|
||||||
|
// image at the same time is not a good idea. Therefore, we simply create
|
||||||
|
// a new renderer here.
|
||||||
|
this->render_ = std::make_unique<CvMatRender>(*this->cached_image_);
|
||||||
this->is_dirty_ = false;
|
this->is_dirty_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,8 +65,8 @@ void pixelarium::render::PixelariumImageViewCzi::ShowImage()
|
|||||||
auto new_dim = ImGui::GetContentRegionAvail();
|
auto new_dim = ImGui::GetContentRegionAvail();
|
||||||
auto texture =
|
auto texture =
|
||||||
dim_changed_p(this->curr_dim_, new_dim)
|
dim_changed_p(this->curr_dim_, new_dim)
|
||||||
? this->render_.Render(static_cast<size_t>(this->curr_dim_.x), static_cast<size_t>(this->curr_dim_.y))
|
? this->render_->Render(static_cast<size_t>(this->curr_dim_.x), static_cast<size_t>(this->curr_dim_.y))
|
||||||
: this->render_.Render();
|
: this->render_->Render();
|
||||||
|
|
||||||
this->curr_dim_ = new_dim;
|
this->curr_dim_ = new_dim;
|
||||||
|
|
||||||
@@ -53,12 +80,22 @@ void pixelarium::render::PixelariumImageViewCzi::ShowImage()
|
|||||||
ImGui::Text("%s", std::format("Render Dimensions W : {}, H: {}", curr_dim_.x, curr_dim_.y).c_str());
|
ImGui::Text("%s", std::format("Render Dimensions W : {}, H: {}", curr_dim_.x, curr_dim_.y).c_str());
|
||||||
ImGui::Text("Dimensions");
|
ImGui::Text("Dimensions");
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
if (ImGui::Button("Update"))
|
||||||
|
{
|
||||||
|
this->ForceUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
auto stats = czi_img->GetStatistics();
|
auto stats = czi_img->GetStatistics();
|
||||||
stats.dimBounds.EnumValidDimensions(
|
stats.dimBounds.EnumValidDimensions(
|
||||||
[&](libCZI::DimensionIndex dim, int start, int size) -> bool
|
[&](libCZI::DimensionIndex dim, int start, int size) -> bool
|
||||||
{
|
{
|
||||||
ImGui::Text("%c\t Start: %d\t End: %d", libCZI::Utils::DimensionToChar(dim), start, size);
|
auto dim_char = libCZI::Utils::DimensionToChar(dim);
|
||||||
|
if (ImGui::SliderInt(std::format("{}({}-{})", dim_char, start, size).c_str(), &dimension_map_[dim], start,
|
||||||
|
size - 1))
|
||||||
|
{
|
||||||
|
this->ForceUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,25 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
|
#include "libCZI_DimCoordinate.h"
|
||||||
|
#include "rendering/CvMatRender.hpp"
|
||||||
#include "rendering/IPixelariumImageView.hpp"
|
#include "rendering/IPixelariumImageView.hpp"
|
||||||
|
#include "utilities/ILog.hpp"
|
||||||
|
|
||||||
namespace pixelarium::render
|
namespace pixelarium::render
|
||||||
{
|
{
|
||||||
|
/// @brief A CZI-specific implementation of IPixelariumImageView.
|
||||||
class PixelariumImageViewCzi : public IPixelariumImageView
|
class PixelariumImageViewCzi : public IPixelariumImageView
|
||||||
{
|
{
|
||||||
using Image = imaging::IPixelariumImage;
|
using Image = imaging::IPixelariumImage;
|
||||||
using Render = render::CvMatRender;
|
using Render = render::CvMatRender;
|
||||||
|
using Log = utils::log::ILog;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit PixelariumImageViewCzi(std::shared_ptr<Image> img)
|
explicit PixelariumImageViewCzi(std::shared_ptr<Image> img, const Log& log);
|
||||||
{
|
|
||||||
img_ = img;
|
|
||||||
render_ = Render(img_);
|
|
||||||
}
|
|
||||||
PixelariumImageViewCzi() = delete;
|
PixelariumImageViewCzi() = delete;
|
||||||
PixelariumImageViewCzi(PixelariumImageViewCzi&) = delete;
|
PixelariumImageViewCzi(PixelariumImageViewCzi&) = delete;
|
||||||
PixelariumImageViewCzi(const PixelariumImageViewCzi&) = delete;
|
PixelariumImageViewCzi(const PixelariumImageViewCzi&) = delete;
|
||||||
@@ -27,5 +31,8 @@ class PixelariumImageViewCzi : public IPixelariumImageView
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
ImVec2 curr_dim_{};
|
ImVec2 curr_dim_{};
|
||||||
|
const Log& log_;
|
||||||
|
std::unordered_map<libCZI::DimensionIndex, int> dimension_map_;
|
||||||
|
std::unique_ptr<CvMatRender> render_;
|
||||||
};
|
};
|
||||||
} // namespace pixelarium::render
|
} // namespace pixelarium::render
|
||||||
|
|||||||
@@ -9,16 +9,18 @@
|
|||||||
|
|
||||||
namespace pixelarium::render
|
namespace pixelarium::render
|
||||||
{
|
{
|
||||||
|
/// @brief A default implementation of IPixelariumImageView.
|
||||||
|
/// This is sufficient for single dimension images like png or jpg.
|
||||||
class PixelariumImageViewDefault : public IPixelariumImageView
|
class PixelariumImageViewDefault : public IPixelariumImageView
|
||||||
{
|
{
|
||||||
using Image = imaging::IPixelariumImage;
|
using Image = imaging::IPixelariumImage;
|
||||||
using Render = render::CvMatRender;
|
using Render = render::CvMatRender;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit PixelariumImageViewDefault(std::shared_ptr<Image> img)
|
explicit PixelariumImageViewDefault(std::shared_ptr<Image> img) : render_(*img->TryGetImage())
|
||||||
{
|
{
|
||||||
img_ = img;
|
img_ = img;
|
||||||
render_ = Render(img_);
|
this->SetInitialSize();
|
||||||
}
|
}
|
||||||
PixelariumImageViewDefault() = delete;
|
PixelariumImageViewDefault() = delete;
|
||||||
PixelariumImageViewDefault(PixelariumImageViewDefault&) = delete;
|
PixelariumImageViewDefault(PixelariumImageViewDefault&) = delete;
|
||||||
@@ -31,5 +33,6 @@ class PixelariumImageViewDefault : public IPixelariumImageView
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
ImVec2 curr_dim_{};
|
ImVec2 curr_dim_{};
|
||||||
|
CvMatRender render_;
|
||||||
};
|
};
|
||||||
} // namespace pixelarium::render
|
} // namespace pixelarium::render
|
||||||
|
|||||||
@@ -48,8 +48,13 @@ void pixelarium::render::RenderImageManager::Add(resources::ResourceKey key) noe
|
|||||||
{
|
{
|
||||||
// we don't want to add what's already there
|
// we don't want to add what's already there
|
||||||
// or empty render images
|
// or empty render images
|
||||||
|
if (this->render_image_map_.contains(key))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto current_view = this->view_factory_->RenderImage(key);
|
auto current_view = this->view_factory_->RenderImage(key);
|
||||||
if (this->render_image_map_.contains(key) || current_view == nullptr)
|
if (current_view == nullptr)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,14 @@ struct RenderImageStateWrapper
|
|||||||
const bool* show_state;
|
const bool* show_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/// @brief Manage instances of IPixelariumImageView.
|
||||||
|
///
|
||||||
|
/// This class is used to keep track of what must be rendered.
|
||||||
|
/// It manages a set of IPixelariumImageView instances that can be traversed
|
||||||
|
/// via its Enumerate() function.
|
||||||
|
/// Views that shall not be rendered anymore should be marked for deletion
|
||||||
|
/// with MarkForDeletion()
|
||||||
class RenderImageManager
|
class RenderImageManager
|
||||||
{
|
{
|
||||||
using Pool = resources::ImageResourcePool;
|
using Pool = resources::ImageResourcePool;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ namespace pixelarium::resources
|
|||||||
{
|
{
|
||||||
using ResourceKey = size_t;
|
using ResourceKey = size_t;
|
||||||
|
|
||||||
|
/// @brief A dedicated exception to be thrown when a resource of an IResourcePool is empty.
|
||||||
struct empty_resource_exception : public std::exception
|
struct empty_resource_exception : public std::exception
|
||||||
{
|
{
|
||||||
empty_resource_exception() {};
|
empty_resource_exception() {};
|
||||||
@@ -22,15 +23,21 @@ struct empty_resource_exception : public std::exception
|
|||||||
std::string message_ = "Empty Resource";
|
std::string message_ = "Empty Resource";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// @brief Abstract representation of a Resource.
|
||||||
|
/// This is meant to be implemented by arbitrary explicit resource types and thus
|
||||||
|
/// gives no contract other than the abstract type.
|
||||||
struct IResource
|
struct IResource
|
||||||
{
|
{
|
||||||
virtual ~IResource() = default;
|
virtual ~IResource() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// @brief Defines a concept for a resource type
|
||||||
|
/// @tparam R The resource template parameter
|
||||||
template <typename R>
|
template <typename R>
|
||||||
concept ResT = requires(R& r) { static_cast<IResource&>(r); };
|
concept ResT = requires(R& r) { static_cast<IResource&>(r); };
|
||||||
|
|
||||||
|
/// @brief Defines an interface for a resource pool
|
||||||
|
/// @tparam ResT defines the resource type that is accepted by the pool
|
||||||
template <typename ResT>
|
template <typename ResT>
|
||||||
class IResourcePool
|
class IResourcePool
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#define __PRETTY_FUNCTION__ __FUNCTION__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace pixelarium::utils::log
|
namespace pixelarium::utils::log
|
||||||
{
|
{
|
||||||
enum class LogLevel
|
enum class LogLevel
|
||||||
@@ -11,6 +16,7 @@ enum class LogLevel
|
|||||||
Warn = 1 << 3,
|
Warn = 1 << 3,
|
||||||
Error = 1 << 4,
|
Error = 1 << 4,
|
||||||
};
|
};
|
||||||
|
/// @brief Interface for logging implementations.
|
||||||
class ILog
|
class ILog
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
#include "ILog.hpp"
|
#include "ILog.hpp"
|
||||||
namespace pixelarium::utils::log
|
namespace pixelarium::utils::log
|
||||||
{
|
{
|
||||||
|
/// @brief Implements ILog using the spdlog library
|
||||||
|
/// see https://github.com/gabime/spdlog
|
||||||
class SpdLogger : public ILog
|
class SpdLogger : public ILog
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
Reference in New Issue
Block a user