title: Displaying an image with Pygobject and Python 3 from in-memory data
body: <p>I have some RGBA data in Python 3 and I want to display the image it represents in a GTK3 window without using any extra libraries.</p>
  
  <p>First thing I tried was editing a <code>Pixbuf</code>'s data as in an example (http://developer.gnome.org/gdk-pixbuf/stable/gdk-pixbuf-The-GdkPixbuf-Structure.html#put-pixel - sorry, I'm only allowed 2 links) in the (C) documentation, using <code>Pixbuf.get_pixels()</code>.  This gives me an immutable <code>bytes</code> object, though, and so obviously won't work.  (A gdk-pixbuf bug report (668084, would link to it if SO would let me) covers the same function, but stuff must've changed a bit since.)</p>
  
  <p>Next, I tried creating a Pixbuf from the data using <a href="http://developer.gnome.org/gdk-pixbuf/stable/gdk-pixbuf-Image-Data-in-Memory.html#gdk-pixbuf-new-from-data"><code>Pixbuf.new_from_data()</code></a>, but this is buggy too (see gdk-pixbuf bug 674691) (yes, that's me in comment 3).</p>
  
  <p>Then I looked at Cairo: <a href="http://cairographics.org/documentation/pycairo/3/reference/surfaces.html#cairo.ImageSurface.create_for_data"><code>ImageSurface.create_for_data</code></a> should do this, but for some reason this isn't available in the Python 3 binding yet.  (I have tried this with Python 2, turning the surface into a <code>Pixbuf</code> afterwards and then wrapping that in a <code>gtk.Image</code>, and it works.  But I'm using Python3 (and even then, it's messy - Cairo is a vector graphics library, after all)).</p>
  
  <p>I found a reference somewhere to using PIL to write the image out to a PNG file then reading that into a Pixbuf, but this is horrible, uses an extra library, and PIL isn't available for Python 3 anyway.</p>
  
  <p>So...any other methods?</p>
  
  <h2>Working code</h2>
  
  <p>Based on Havok's answer, here's a working example:</p>
  
  <pre><code>from array import array
  
  from gi.repository import Gtk as gtk, GdkPixbuf
  
  pixels = array('H')
  for i in range(20):
      for j in range(20):
          px = (i &lt; 10, j &gt;= 10, (i &lt; 10) ^ (j &lt; 10))
          pixels.extend(65535 * c for c in px)
  
  header = b'P6 20 20 65535 '
  img_data = header + pixels
  
  w = gtk.Window()
  w.connect('delete-event', gtk.main_quit)
  l = GdkPixbuf.PixbufLoader.new_with_type('pnm')
  l.write(img_data)
  w.add(gtk.Image.new_from_pixbuf(l.get_pixbuf()))
  l.close()
  w.show_all()
  gtk.main()
  </code></pre>
  
  <p>Edit: actually, for correctness, I think this will need a <code>pixels.byteswap()</code> on little-endian systems before adding to the header (though of course it doesn't matter with these colours).</p>