Robot Monitor
// Copyright (C) 2026 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "rosimageitem.h"
RosImageItem::RosImageItem()
{
setFlag(ItemHasContents, true);
}
void RosImageItem::setImage(const Qtros2SensorMsgs::Image &img)
{
// Simple check to avoid redundant updates if data hasn't changed.
// For video streams, we usually just check if data size or timestamp differs.
if (m_image.header().stamp() == img.header().stamp()
&& m_image.data().size() == img.data().size()) {
return;
}
m_image = img;
m_dirty = true;
emit imageChanged();
update(); // Schedule a repaint
}
QSGNode *RosImageItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
auto node = static_cast<QSGSimpleTextureNode *>(oldNode);
if (m_image.data().isEmpty()) {
return node;
}
if (!node) {
node = new QSGSimpleTextureNode();
node->setFiltering(QSGTexture::Linear);
}
if (m_dirty) {
QImage::Format format = QImage::Format_Invalid;
const QString encoding = m_image.encoding();
// --- Corrected Mappings ---
if (encoding == "rgb8")
format = QImage::Format_RGB888;
else if (encoding == "bgr8")
format = QImage::Format_BGR888;
else if (encoding == "rgba8")
format = QImage::Format_RGBA8888;
// FIX: Use ARGB32 for BGRA data on Little Endian systems
else if (encoding == "bgra8")
format = QImage::Format_ARGB32;
else if (encoding == "mono8")
format = QImage::Format_Grayscale8;
if (format != QImage::Format_Invalid) {
// Zero-Copy Wrapper
QImage wrapper(reinterpret_cast<const uchar *>(m_image.data().constData()),
m_image.width(),
m_image.height(),
m_image.step(),
format);
// If existing texture matches size, we can update it; otherwise recreate.
if (node->texture()) {
delete node->texture();
}
QSGTexture *tex = window()->createTextureFromImage(wrapper);
node->setTexture(tex);
node->setRect(boundingRect());
}
m_dirty = false;
}
node->setRect(boundingRect());
return node;
}