Изображение, созданное с помощью Gdk::Pixbuf, искажается при отображении

  1. Я пытаюсь отобразить изображение в окне.
  2. Я использую C++ с библиотеками Gtkmm и Gdkmm.
  3. Я читаю образ с диска и создаю Gdk::Pixbuf
  4. Затем я отображаю его в виджете. Вот что я вижу на экране:

введите здесь описание изображения

  1. Фактическое изображение должно выглядеть так:

введите здесь описание изображения

Код на С++ ниже:

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;
}

Вот некоторая справочная информация:

  1. Сохраненный файл PNG не искажен - он выглядит так, как должен! Проблема видимо только с дисплеем.

  2. Я пробовал один и тот же код на двух системах (MacOS и Debian). Проблема только в системе Debian (MacOS отображает правильную картинку).

  3. Я использую одни и те же библиотеки в обеих системах, но разные версии компилятора g++.

  4. Если вместо этого я создам Pixbuf из файла PNG, отображаемое изображение снова будет правильным.


Есть ли способ устранить неполадки? Я что-то пропустил?


person Cerelac Holmes    schedule 23.05.2019    source источник
comment
какая версия gtk+ у вас установлена ​​на обеих системах?   -  person Igor    schedule 23.05.2019
comment
Я использую gtk+3 в обеих системах.   -  person Cerelac Holmes    schedule 23.05.2019
comment
в документации ничего не сказано, но я предполагаю, что Gdk::Pixbuf::create_from_data не копирует данные, image_rgb выходит за рамки в конце функции, а ваш Pixbuf указывает на мусор.   -  person Alan Birtles    schedule 23.05.2019


Ответы (1)


Gdk::Pixbuf::create_from_data не копирует данные. image_rgb выходит за рамки в конце вашей функции, а Pixbuf указывает на ненужные данные.

Самое простое решение — просто скопировать Pixbuf при возврате:

return Pixbuf_from_data.copy()

Это создает копию данных, принадлежащих объекту PixBuf. Вы можете избежать копирования, разместив свои данные в куче и используя аргумент const SlotDestroyData& destroy_slot для create_from_data, чтобы удалить его при уничтожении PixBuf.

person Alan Birtles    schedule 23.05.2019
comment
Спасибо, похоже дело было в этом! Я полностью пропустил это. - person Cerelac Holmes; 23.05.2019