Search code examples
c++gtkgtk3magick++gtkmm3

What is the preferred approach to display a Magick++ Image in a GTK+3 application?


I'm working on an C++ image viewer for Linux which is created using GTK+3 (gtkmm) for the GUI and Magick++ for image handling. My goal is to support as many image file formats as possible, including animated GIFs.

What is the best approach to take a Magick++ Image and draw it in a GTK+3 widget, such that it would work for (just about) any image file format?


Solution

  • What is the best approach to take a Magick++ Image and draw it in a GTK+3 widget, such that it would work for (just about) any image file format?

    As long as ImageMagick has the format delegate, you should be able to draw the GtkWidget image.

    image = Gtk::manage(new Gtk::Image());
    // Load image into ImageMagick
    Magick::Image img("wizard:");
    /// Calculate how much memory to allocate
    size_t to_allocate = img.columns() * img.rows() * 3;
    // Create a buffer
    guint8 * buffer = new guint8[to_allocate];
    // Write pixel data to buffer.
    img.write(0, 0, img.columns(), img.rows(), "RGB", Magick::CharPixel, buffer);
    // Build a Pixbuf from pixel data in memory.
    Glib::RefPtr<Gdk::Pixbuf> pBuff = Gdk::Pixbuf::create_from_data(buffer, Gdk::COLORSPACE_RGB, false, 8, img.columns(), img.rows(), img.columns()*3 );
    // Set GtkImage from Pixbuf
    image->set(pBuff);
    

    GtkImage from Magick++

    Original Answer mixing C/C++ methods.

    Use the following Magick++ method signature to export the pixel data into memory.

    Magick::Image.write(const ssize_t x_,
                        const ssize_t y_,
                        const size_t columns_,
                        const size_t rows_,
                        const std::string &map_,           //<= Usually "RGB"
                        const StorageType type_,           //<= Usually CharType
                        void *pixels_)                     //<= Be sure to allocate _all_ the memory required (size of storage * number of channels * columns * rows)
    

    Create a GdkPixBuf from the pixels exported above with the following GTK method.

    GdkPixbuf *
    gdk_pixbuf_new_from_bytes (GBytes *data,               //<= Same as pixels_.
                               GdkColorspace colorspace,   //<= Match colorspace channels from map_.
                               gboolean has_alpha,         //<= Usually no.
                               int bits_per_sample,        //<= Match StorageType bits
                               int width,                  //<= Same as columns_.
                               int height,                 //<= Same as rows_.
                               int rowstride);             //<= size of data-type * number of channel * width.
    

    Finally, build a GtkImage from the PixBuf with the following method.

    GtkWidget * gtk_image_new_from_pixbuf (GdkPixbuf *pixbuf);