Reputation: 37
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:
The saved PNG file isn't garbled - it appears as it should! The issue seems to be just with the display.
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).
I use the same libraries across both systems, but different versions of the g++ compiler.
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?
Upvotes: 0
Views: 512
Reputation: 36379
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.
Upvotes: 2