Misc (#19)
* get image returns optional<Mat> instead of unique_ptr<Mat> * introduce complexity * rename image load function * add example for a basic reader for binary image files * fix windows build? * add a status bar underneath the menu bar * use status bar in custom_0 example app * clang formats * packing w/ pragma push * add "Save As" functions to image views * resize over reserve * rm local override uri * add simple thread pool * rename to simple_thread_pool * get rid of useless renderlib * document version inc * extract hardcoded values to in-header * clang format patch * clone registered image in custom_0 * document binary-file header * minor fixes * clang format * rm unused render cmake
This commit is contained in:
committed by
Maximilian Kueffner
parent
e3e161ce52
commit
b37814204f
@@ -0,0 +1,123 @@
|
||||
#include "CvMatRender.hpp"
|
||||
|
||||
#include <opencv2/core/mat.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
|
||||
#include "imaging/IPixelariumImage.hpp"
|
||||
|
||||
using namespace pixelarium::imaging;
|
||||
|
||||
/// @brief Constructor for the CvMatRender class.
|
||||
/// @param img A shared pointer to the PixelariumImage to be rendered.
|
||||
pixelarium::application::CvMatRender::CvMatRender(const cv::Mat& img) : base_(img), texture_(0)
|
||||
{
|
||||
// storing a copy of the to-be-rendered image
|
||||
// because it will be resized and filtered eventually which we absolutely
|
||||
// must not do on the original image
|
||||
this->ResetRenderImage();
|
||||
cv::cvtColor(this->img_, this->img_, cv::COLOR_BGR2RGBA);
|
||||
}
|
||||
|
||||
/// @brief Destructor for the CvMatRender class.
|
||||
/// Deallocates the OpenGL texture if it exists.
|
||||
pixelarium::application::CvMatRender::~CvMatRender()
|
||||
{
|
||||
if (texture_)
|
||||
{
|
||||
glDeleteTextures(1, &texture_);
|
||||
texture_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Uploads the current image data to an 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.
|
||||
GLuint pixelarium::application::CvMatRender::uploadTexture()
|
||||
{
|
||||
if (img_.empty())
|
||||
{
|
||||
throw std::runtime_error("Image data is empty.");
|
||||
}
|
||||
|
||||
if (!this->texture_)
|
||||
{
|
||||
glGenTextures(1, &this->texture_);
|
||||
if (this->texture_ == 0)
|
||||
{
|
||||
throw std::runtime_error("Failed to generate OpenGL texture.");
|
||||
}
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, this->texture_);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
const int width = img_.cols;
|
||||
const int height = img_.rows;
|
||||
// see
|
||||
// https://stackoverflow.com/questions/10167534/how-to-find-out-what-type-of-a-mat-object-is-with-mattype-in-opencv
|
||||
// for pixel a pixel type table
|
||||
switch (img_.type())
|
||||
{
|
||||
case CV_8U:
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_BYTE, img_.data);
|
||||
break;
|
||||
case CV_16U:
|
||||
case CV_16UC3:
|
||||
case CV_16UC4:
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT, img_.data);
|
||||
break;
|
||||
case CV_32F:
|
||||
case CV_32FC4:
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
|
||||
img_.data);
|
||||
break;
|
||||
default:
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img_.cols, img_.rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, img_.data);
|
||||
break;
|
||||
}
|
||||
|
||||
GLenum error = glGetError();
|
||||
if (error != GL_NO_ERROR)
|
||||
{
|
||||
throw std::runtime_error("OpenGL error during texture upload: " + std::to_string(error));
|
||||
}
|
||||
|
||||
return this->texture_;
|
||||
}
|
||||
|
||||
/// @brief Renders the image by uploading it as a texture.
|
||||
/// @return The ID of the OpenGL texture.
|
||||
GLuint pixelarium::application::CvMatRender::Render() { return this->uploadTexture(); }
|
||||
|
||||
/// @brief Renders the image with a specified scaling factor.
|
||||
/// @param factor The scaling factor for resizing the image.
|
||||
/// @return The ID of the OpenGL texture.
|
||||
GLuint pixelarium::application::CvMatRender::Render(float factor)
|
||||
{
|
||||
cv::resize(this->base_, this->img_, cv::Size(0, 0), factor, factor, cv::INTER_LINEAR_EXACT);
|
||||
|
||||
return this->uploadTexture();
|
||||
}
|
||||
|
||||
/// @brief Renders the image to fit within the specified width and height.
|
||||
/// @param width The maximum width of the rendered image.
|
||||
/// @param height The maximum height of the rendered image.
|
||||
/// @return The ID of the OpenGL texture.
|
||||
GLuint pixelarium::application::CvMatRender::Render(size_t width, size_t height)
|
||||
{
|
||||
const auto sz{this->base_.size()};
|
||||
|
||||
const auto get_factor = [](auto opt1, auto opt2) -> float { return opt1 < opt2 ? opt1 : opt2; };
|
||||
|
||||
auto factor = get_factor(width / static_cast<float>(sz.width), height / static_cast<float>(sz.height));
|
||||
|
||||
return this->Render(factor);
|
||||
}
|
||||
|
||||
void pixelarium::application::CvMatRender::ResetRenderImage()
|
||||
{
|
||||
// we copy here
|
||||
this->img_ = this->base_.clone();
|
||||
}
|
||||
Reference in New Issue
Block a user