From 22548efd45608461fc57bd9fa74adae3afe12666 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Hern=C3=A1ndez=20Cordero?= Date: Tue, 26 May 2026 10:17:56 +0200 Subject: [PATCH 1/2] Fix when with pitch != width*BBP in Image Display (#1719) Signed-off-by: Alejandro Hernandez Cordero (cherry picked from commit 9eebc57c6b949466c95869d6a31a878cf10bf222) --- .../displays/image/ros_image_texture.cpp | 58 ++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/rviz_default_plugins/src/rviz_default_plugins/displays/image/ros_image_texture.cpp b/rviz_default_plugins/src/rviz_default_plugins/displays/image/ros_image_texture.cpp index e3c0ac413..74fb21a6f 100644 --- a/rviz_default_plugins/src/rviz_default_plugins/displays/image/ros_image_texture.cpp +++ b/rviz_default_plugins/src/rviz_default_plugins/displays/image/ros_image_texture.cpp @@ -41,6 +41,8 @@ #include #include +#include + #include // NOLINT: cpplint cannot handle include order #include "sensor_msgs/image_encodings.hpp" @@ -133,6 +135,26 @@ void ROSImageTexture::setNormalizeFloatImage(bool normalize, double min, double max_ = max; } +// Bytes per pixel for encodings that have a fixed linear row layout. Returns +// 0 for encodings whose per-row layout is non-trivial (YUV 4:2:2 packed, NV12 +// planar) — those are handled explicitly by their converters using stride. +static size_t bytesPerPixelForEncoding(const std::string & encoding) +{ + namespace enc = sensor_msgs::image_encodings; + if (encoding == enc::YUV422 || encoding == enc::YUV422_YUY2 || + encoding == enc::UYVY || encoding == enc::YUYV || + encoding == enc::NV12 || encoding == enc::NV21 || encoding == enc::NV24) + { + return 0; + } + try { + return static_cast(enc::numChannels(encoding)) * + enc::bitDepth(encoding) / 8; + } catch (const std::runtime_error &) { + return 0; // unknown encoding — skip repack + } +} + static double computeMedianOfSeveralFrames(std::deque & buffer, double value, unsigned median_frames) { @@ -167,8 +189,42 @@ bool ROSImageTexture::update() height_ = image->height; stride_ = image->step; + // If the publisher sent rows with trailing padding (step > width * bpp), + // repack into a contiguous buffer. Ogre::Image::loadRawData and the + // convertTo8bit rescale loop both assume packed rows — without this, + // each row drifts right by `padding` bytes, producing a diagonal shear. + // YUV/NV12 encodings are left alone because their converters honor stride + // directly. + std::vector repacked; + const uint8_t * data_ptr = image->data.data(); + size_t data_size = image->data.size(); + const size_t bpp = bytesPerPixelForEncoding(image->encoding); + if (bpp != 0) { + const size_t packed_row = static_cast(width_) * bpp; + if (stride_ > packed_row) { + if (image->data.size() < static_cast(stride_) * height_) { + RVIZ_COMMON_LOG_ERROR_STREAM( + "Image data size " << image->data.size() << + " smaller than step*height (" << stride_ * height_ << ")"); + return false; + } + repacked.resize(packed_row * height_); + for (uint32_t y = 0; y < height_; ++y) { + std::memcpy( + repacked.data() + y * packed_row, + image->data.data() + y * stride_, + packed_row); + } + data_ptr = repacked.data(); + data_size = repacked.size(); + // Reflect the repack so any downstream code reading stride_ sees the + // new (packed) layout. + stride_ = packed_row; + } + } + ImageData image_data = setFormatAndNormalizeDataIfNecessary( - image->encoding, image->data.data(), image->data.size()); + image->encoding, data_ptr, data_size); Ogre::Image ogre_image; try { From 3fdaf563b73fe96208616f75ce0e2f6d54e2821c Mon Sep 17 00:00:00 2001 From: Alejandro Hernandez Cordero Date: Tue, 2 Jun 2026 12:11:54 +0200 Subject: [PATCH 2/2] fix Signed-off-by: Alejandro Hernandez Cordero --- .../rviz_default_plugins/displays/image/ros_image_texture.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rviz_default_plugins/src/rviz_default_plugins/displays/image/ros_image_texture.cpp b/rviz_default_plugins/src/rviz_default_plugins/displays/image/ros_image_texture.cpp index 74fb21a6f..1efd85324 100644 --- a/rviz_default_plugins/src/rviz_default_plugins/displays/image/ros_image_texture.cpp +++ b/rviz_default_plugins/src/rviz_default_plugins/displays/image/ros_image_texture.cpp @@ -143,7 +143,7 @@ static size_t bytesPerPixelForEncoding(const std::string & encoding) namespace enc = sensor_msgs::image_encodings; if (encoding == enc::YUV422 || encoding == enc::YUV422_YUY2 || encoding == enc::UYVY || encoding == enc::YUYV || - encoding == enc::NV12 || encoding == enc::NV21 || encoding == enc::NV24) + encoding == enc::NV21 || encoding == enc::NV24) { return 0; }