Search code examples
c++gtkmm3gdkpixbuf

Image created using Gdk::Pixbuf is garbled upon display


  1. I'm trying to display an image in a window.
  2. I'm using C++ with the Gtkmm and Gdkmm libraries.
  3. I read the image from disk and create a Gdk::Pixbuf
  4. I then display it in a widget. Here's what I see on screen:

enter image description here

  1. The actual image is supposed to look like this:

enter image description here

The code in C++ is below:

template <typename type>
Glib::RefPtr<Gdk::Pixbuf> get_pixbuf_from_image(array<type>& image){

  // Get dimensions of image
  vlong img_dims = image.get_dims();

  // Get number of elements and multiply by the number of channels
  vlong rgb_dims{3*static_cast<long>(image.get_size())};

  // Create a new RGB array of type <guint8> 
  array<guint8> image_rgb(rgb_dims);

  // Find maximum and minimum pixel value of image.
  type maximum = -1E6;
  type minimum =  1E6;
  for(int i=0; i<image.get_size(); i++){
    maximum = (image.data[i] > maximum) ? image.data[i] : maximum;
    minimum = (image.data[i] < minimum) ? image.data[i] : minimum;
  }

  // Rescale pixel values to [0, 255], and store in RGB array.
  for(int i=0; i<image.get_size(); i++){
      image_rgb.data[3*i+0] = guint8(254*(image.data[i]-minimum)/(maximum-minimum)); // Red channel
      image_rgb.data[3*i+1] = guint8(254*(image.data[i]-minimum)/(maximum-minimum)); // Green channel
      image_rgb.data[3*i+2] = guint8(254*(image.data[i]-minimum)/(maximum-minimum)); // Blue channel
  }

  // Create a Pixbuf from (guint8*)image_rgb.data 
  Glib::RefPtr<Gdk::Pixbuf> Pixbuf_from_data(Gdk::Pixbuf::create_from_data(image_rgb.data, Gdk::COLORSPACE_RGB, false, BITS_PER_SAMPLE, img_dims[1], img_dims[0], 3*img_dims[1]*sizeof(guint8)));

  // Save Pixbuf to PNG file.                                                              
  Pixbuf_from_data->save("picture.png", "png");

  // Return Pixbuf to caller for displaying. 
  return Pixbuf_from_data;
}

Here's some background information:

  1. The saved PNG file isn't garbled - it appears as it should! The issue seems to be just with the display.

  2. I've tried the same code on two systems (MacOS, and Debian). The problem is only on the Debian system (MacOS displays the right picture).

  3. I use the same libraries across both systems, but different versions of the g++ compiler.

  4. If I create the Pixbuf from from a PNG file instead, the displayed image is correct again.


Is there a way to troubleshoot what's going wrong? Am I missing something?


Solution

  • Gdk::Pixbuf::create_from_data doesn't copy the data. image_rgb goes out of scope at the end of your function and the Pixbuf is then pointing to junk data.

    The simplest fix is to just copy the Pixbuf when you return it:

    return Pixbuf_from_data->copy()
    

    This makes a copy of the data which is owned by the PixBuf object. You can avoid the copy by allocating your data on the heap and using the const SlotDestroyData& destroy_slot argument to create_from_data to delete it when the PixBuf is destroyed.