I’d like to display a vector of bytes in a bgr888 format in an sdl window with minimal copies and without looping on every pixel.
If I create a texture with SDL_PixelFormatBGR888 then update the texture with the vector .data()
and image step/pitch size I see colors bands, there is a column of green pixels, then red then blue. The values I set can make the color bands lighter or darker only.
If I create the texture with SDL_PixelFormatBGRA8888 I can create a test pattern in the bytes that appears as I expect without the color bands.
I was expecting the BGR888 texture to get converted under the hood for free or at least much quicker than if I made a for loop that manually copied 3 bgr bytes from the incoming vector and assigned them to the 4 bgra bytes, maybe I’m missing something that can cause this to happen? Or is it that BGR888 is not a blue byte followed by a green then red byte and repeat for every pixel in every row, and every row in the height, some other layout is in use?
buffer = SDL_CreateTexture(
ren_,
// TODO(lucasw) need to match on the msg->encoding
// This doesn't display correctly
SDL_PIXELFORMAT_BGR888,
// SDL_PIXELFORMAT_BGRA8888,
// SDL_TEXTUREACCESS_STREAMING,
SDL_TEXTUREACCESS_STATIC,
msg->width,
msg->height);
std::vector<Uint8> pixels;
pixels.resize(msg->step * msg->height);
for (size_t i = 0; i < pixels.size() - 3; i+=3) {
// for (size_t i = 0; i < pixels.size() - 4; i+=4) {
// test pattern
pixels[i] = (i % msg->step) % 255;
pixels[i + 1] = 0xff;
pixels[i + 2] = (i / msg->step) % 255;
// pixels[i + 3] = 0xff;
}
SDL_Rect msg_rect;
msg_rect.x = 0;
msg_rect.y = 0;
msg_rect.w = msg->width;
msg_rect.h = msg->height;
// This seg faults unless 50 lines of padding are added to the texture
// SDL_UpdateTexture(buffer_, &msg_rect, msg->data.data(), msg->step);
const int rv0 = SDL_UpdateTexture(buffer, &msg_rect, pixels.data(), msg->step);
if (rv0 != 0) {
ROS_ERROR_STREAM("sdl update texture failed: " << SDL_GetError());
return;
}
SDL_Rect dst_rect;
dst_rect.x = 0;
dst_rect.y = 0;
dst_rect.w = std::min(msg->width, width);
dst_rect.h = std::min(msg->height, height);
// ROS_INFO_STREAM("updated " << dst_rect.w << " " << dst_rect.h);
SDL_Rect src_rect = dst_rect;
const int rv1 = SDL_RenderCopy(ren_, buffer, &src_rect, &dst_rect);
if (rv1 != 0) {
ROS_ERROR_STREAM("sdl render copy failed: " << SDL_GetError());
return;
}
SDL_RenderPresent(ren_);
The source code is here sdl2_ros/view_image.cpp at master · lucasw/sdl2_ros · GitHub