9#include <spdlog/spdlog.h>
10#include <QMutexLocker>
11#include <QSGSimpleTextureNode>
13#include <QQuickWindow>
26 setFlag(QQuickItem::ItemHasContents,
true);
27 spdlog::debug(
"[SGSImageItem::SGSImageItem]: Created");
35 spdlog::debug(
"[SGSImageItem::~SGSImageItem()]: Destroyed");
42 if (!image || !image->isValid())
44 spdlog::warn(
"[SGSImageItem::setImage]: Invalid image region");
48 spdlog::info(
"[SGSImageItem::setImage]: {}x{}", image->width(), image->height());
61 QMetaObject::invokeMethod(
this, &QQuickItem::update, Qt::QueuedConnection);
68 if (!tile || !tile->isValid()) {
69 spdlog::warn(
"[SGSImageItem::updateTile]: Invalid tile");
77 spdlog::warn(
"[SGSImageItem::updateTile]: No base image");
86 const size_t data_size { tile->width() * tile->height() * tile->channels() };
87 std::copy(tile->getBuffer().data(),
88 tile->getBuffer().data() + data_size,
91 spdlog::info(
"[SGSImageItem::updateTile]: Full copy {}x{}", tile->width(), tile->height());
95 if (tile->x() < 0 || tile->y() < 0 ||
98 spdlog::warn(
"[SGSImageItem::updateTile]: Tile out of bounds");
103 const size_t row_size { tile->width() * tile->channels() };
104 const int full_w {
static_cast<int>(
m_full_image->width()) };
105 const int tile_x { tile->x() };
106 const int tile_y { tile->y() } ;
107 const int tile_h {
static_cast<int>(tile->height()) };
109 for (
size_t y = 0; y < tile_h; ++y)
111 const float* src = tile->getBuffer().data() + y * row_size;
114 ((tile_y + y) * full_w + tile_x) *
m_full_image->channels();
115 std::copy(src, src + row_size, dst);
117 m_image_dirty =
true;
118 spdlog::debug(
"[SGSImageItem::updateTile]: Partial copy at ({}, {})", tile_x, tile_y);
122 spdlog::debug(
"[SGSImageItem::updateTile]: Merged tile at ({}, {})", tile->x(), tile->y());
123 QMetaObject::invokeMethod(
this, &QQuickItem::update, Qt::QueuedConnection);
136 auto* texture_node {
static_cast<QSGSimpleTextureNode*
>(node) };
140 bool needs_texture_update {
false };
153 needs_texture_update =
true;
156 reinterpret_cast<const uchar*
>(
m_full_image->getBuffer().data()),
158 img_w * 4 *
static_cast<int>(
sizeof(
float)),
159 QImage::Format_RGBA32FPx4
162 const QColorSpace linear_cs { QColorSpace::SRgbLinear };
163 linear_img.setColorSpace(linear_cs);
165 new_qimage = linear_img.convertedToColorSpace(QColorSpace::SRgb)
166 .convertToFormat(QImage::Format_RGBA8888);
168 m_image_dirty =
false;
173 QQuickWindow* win { window() };
176 spdlog::warn(
"[SGSImageItem::updatePaintNode]: No window attached");
181 texture_node =
new QSGSimpleTextureNode();
184 if (needs_texture_update && !new_qimage.isNull())
186 QSGTexture* new_texture { win->createTextureFromImage(
188 QQuickWindow::TextureHasAlphaChannel
192 texture_node->setTexture(new_texture);
193 texture_node->setOwnsTexture(
true);
195 spdlog::warn(
"[SGSImageItem::updatePaintNode]: Failed to create texture");
199 if (texture_node->texture())
201 float display_w, display_h;
202 if (img_w > 0 && img_h > 0) {
203 display_w = img_w *
m_zoom;
204 display_h = img_h *
m_zoom;
210 const float x_pos = (width() - display_w) / 2.0f +
m_pan.x();
211 const float y_pos = (height() - display_h) / 2.0f +
m_pan.y();
213 texture_node->setRect(x_pos, y_pos, display_w, display_h);
214 texture_node->setFiltering(QSGTexture::Linear);
bool isImageValid() const override
Checks if the full image data is loaded and valid. This method provides thread-safe access to check t...
std::unique_ptr< Core::Common::ImageRegion > m_full_image
Unique pointer to the full image data displayed by this item.
QMutex m_image_mutex
Mutex protecting access to m_full_image and related state. Ensures thread-safe updates to the image d...
int imageHeight() const override
Gets the height of the image. This method provides thread-safe access to m_image_height.
QPointF m_pan
Current pan offset applied to the image.
float m_zoom
Current zoom level applied to the image.
int imageWidth() const override
Gets the width of the image. This method provides thread-safe access to m_image_width.
void panChanged(const QPointF &pan)
Signal emitted when the pan offset changes.
void onZoomChanged(float new_zoom) override
void imageSizeChanged()
Signal emitted when the image dimensions change (width or height).
void onImageChanged() override
~SGSImageItem() override
Destroys the SGSImageItem and releases associated resources.
void updateTile(std::unique_ptr< Core::Common::ImageRegion > tile) override
Updates a specific tile of the displayed image.
void onPanChanged(const QPointF &new_pan) override
SGSImageItem(QQuickItem *parent=nullptr)
Constructs a new SGSImageItem.
void setImage(std::unique_ptr< Core::Common::ImageRegion > image) override
Sets the full image to be displayed.
void zoomChanged(float zoom)
Signal emitted when the zoom value changes.
QSGNode * updatePaintNode(QSGNode *node, UpdatePaintNodeData *data) override
Updates the scene graph node for this item.
Namespace containing Qt-specific UI components for CaptureMoment.
Simple texture-based image display (Qt6 - QSGSimpleTextureNode) using BaseImageItem for common state.