<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Drawing Images</title> <link rel="stylesheet" type="text/css" href="style.css"> <meta name="generator" content="DocBook XSL Stylesheets V1.79.1"> <link rel="home" href="index.html" title="Programming with gtkmm 3"> <link rel="up" href="chapter-drawingarea.html" title="Chapter 17. The Drawing Area Widget"> <link rel="prev" href="sec-drawing-text.html" title="Drawing Text"> <link rel="next" href="sec-drawing-clock-example.html" title="Example Application: Creating a Clock with Cairo"> </head> <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> <div class="navheader"> <table width="100%" summary="Navigation header"> <tr><th colspan="3" align="center">Drawing Images</th></tr> <tr> <td width="20%" align="left"> <a accesskey="p" href="sec-drawing-text.html"><img src="icons/prev.png" alt="Prev"></a> </td> <th width="60%" align="center">Chapter 17. The Drawing Area Widget</th> <td width="20%" align="right"> <a accesskey="n" href="sec-drawing-clock-example.html"><img src="icons/next.png" alt="Next"></a> </td> </tr> </table> <hr> </div> <div class="sect1"> <div class="titlepage"><div><div><h2 class="title" style="clear: both"> <a name="sec-draw-images"></a>Drawing Images</h2></div></div></div> <p> There is a method for drawing from a <code class="classname">Gdk::Pixbuf</code> to a <code class="classname">Cairo::Context</code>. A <code class="classname">Gdk::Pixbuf</code> buffer is a useful wrapper around a collection of pixels, which can be read from files, and manipulated in various ways. </p> <p> Probably the most common way of creating <code class="classname">Gdk::Pixbuf</code>s is to use <code class="methodname">Gdk::Pixbuf::create_from_file()</code> or <code class="methodname">Gdk::Pixbuf::create_from_resource()</code>, which can read an image file, such as a png file into a pixbuf ready for rendering. </p> <p> The <code class="classname">Gdk::Pixbuf</code> can be rendered by setting it as the source pattern of the Cairo context with <code class="methodname">Gdk::Cairo::set_source_pixbuf()</code>. Then draw the image with either <code class="methodname">Cairo::Context::paint()</code> (to draw the whole image), or <code class="methodname">Cairo::Context::rectangle()</code> and <code class="methodname">Cairo::Context::fill()</code> (to fill the specified rectangle). <code class="methodname">set_source_pixbuf()</code> is not a member of <code class="classname">Cairo::Context</code>. It takes a <code class="classname">Cairo::Context</code> as its first parameter. </p> <p> Here is a small bit of code to tie it all together: (Note that usually you wouldn't load the image every time in the draw signal handler! It's just shown here to keep it all together.) </p> <pre class="programlisting">bool MyArea::on_draw(const Cairo::RefPtr<Cairo::Context>& cr) { Glib::RefPtr<Gdk::Pixbuf> image = Gdk::Pixbuf::create_from_file("myimage.png"); // Draw the image at 110, 90, except for the outermost 10 pixels. Gdk::Cairo::set_source_pixbuf(cr, image, 100, 80); cr->rectangle(110, 90, image->get_width()-20, image->get_height()-20); cr->fill(); return true; }</pre> <div class="sect2"> <div class="titlepage"><div><div><h3 class="title"> <a name="cairo-example-image"></a>Example</h3></div></div></div> <p> Here is an example of a simple program that draws an image. The program loads the image from a resource file. See the <a class="link" href="sec-gio-resource.html" title="Gio::Resource and glib-compile-resources">Gio::Resource and glib-compile-resources</a> section. Use <span class="application">glib-compile-resources</span> to compile the resources into a C source file that can be compiled and linked with the C++ code. E.g. </p> <pre class="screen">$ glib-compile-resources --target=resources.c --generate-source image.gresource.xml</pre> <p> </p> <div class="figure"> <a name="figure-drawingarea-image"></a><p class="title"><b>Figure 17.7. Drawing Area - Image</b></p> <div class="figure-contents"><div class="screenshot"><div><img src="figures/drawingarea_image.png" alt="Drawing Area - Image"></div></div></div> </div> <br class="figure-break"><p><a class="ulink" href="http://git.gnome.org/browse/gtkmm-documentation/tree/examples/book/drawingarea/image?h=gtkmm-3-24" target="_top">Source Code</a></p> <p>File: <code class="filename">myarea.h</code> (For use with gtkmm 3, not gtkmm 2) </p> <pre class="programlisting"> #ifndef GTKMM_EXAMPLE_MYAREA_H #define GTKMM_EXAMPLE_MYAREA_H #include <gtkmm/drawingarea.h> #include <gdkmm/pixbuf.h> class MyArea : public Gtk::DrawingArea { public: MyArea(); virtual ~MyArea(); protected: //Override default signal handler: bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr) override; Glib::RefPtr<Gdk::Pixbuf> m_image; }; #endif // GTKMM_EXAMPLE_MYAREA_H </pre> <p>File: <code class="filename">main.cc</code> (For use with gtkmm 3, not gtkmm 2) </p> <pre class="programlisting"> #include "myarea.h" #include <gtkmm/application.h> #include <gtkmm/window.h> int main(int argc, char** argv) { auto app = Gtk::Application::create(argc, argv, "org.gtkmm.example"); Gtk::Window win; win.set_title("DrawingArea"); win.set_default_size(300, 200); MyArea area; win.add(area); area.show(); return app->run(win); } </pre> <p>File: <code class="filename">myarea.cc</code> (For use with gtkmm 3, not gtkmm 2) </p> <pre class="programlisting"> #include "myarea.h" #include <cairomm/context.h> #include <giomm/resource.h> #include <gdkmm/general.h> // set_source_pixbuf() #include <glibmm/fileutils.h> #include <iostream> MyArea::MyArea() { try { // The fractal image has been created by the XaoS program. // http://xaos.sourceforge.net m_image = Gdk::Pixbuf::create_from_resource("/image/fractal_image.png"); } catch(const Gio::ResourceError& ex) { std::cerr << "ResourceError: " << ex.what() << std::endl; } catch(const Gdk::PixbufError& ex) { std::cerr << "PixbufError: " << ex.what() << std::endl; } // Show at least a quarter of the image. if (m_image) set_size_request(m_image->get_width()/2, m_image->get_height()/2); } MyArea::~MyArea() { } bool MyArea::on_draw(const Cairo::RefPtr<Cairo::Context>& cr) { if (!m_image) return false; Gtk::Allocation allocation = get_allocation(); const int width = allocation.get_width(); const int height = allocation.get_height(); // Draw the image in the middle of the drawing area, or (if the image is // larger than the drawing area) draw the middle part of the image. Gdk::Cairo::set_source_pixbuf(cr, m_image, (width - m_image->get_width())/2, (height - m_image->get_height())/2); cr->paint(); return true; } </pre> <p>File: <code class="filename">image.gresource.xml</code> (For use with gtkmm 3, not gtkmm 2) </p> <pre class="programlisting"> <?xml version="1.0" encoding="UTF-8"?> <gresources> <gresource prefix="/image"> <file>fractal_image.png</file> </gresource> </gresources> </pre> </div> </div> <div class="navfooter"> <hr> <table width="100%" summary="Navigation footer"> <tr> <td width="40%" align="left"> <a accesskey="p" href="sec-drawing-text.html"><img src="icons/prev.png" alt="Prev"></a> </td> <td width="20%" align="center"><a accesskey="u" href="chapter-drawingarea.html"><img src="icons/up.png" alt="Up"></a></td> <td width="40%" align="right"> <a accesskey="n" href="sec-drawing-clock-example.html"><img src="icons/next.png" alt="Next"></a> </td> </tr> <tr> <td width="40%" align="left" valign="top">Drawing Text </td> <td width="20%" align="center"><a accesskey="h" href="index.html"><img src="icons/home.png" alt="Home"></a></td> <td width="40%" align="right" valign="top"> Example Application: Creating a Clock with Cairo</td> </tr> </table> </div> </body> </html>