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.
First thing I tried was editing a Pixbuf
'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 Pixbuf.get_pixels()
. This gives me an immutable bytes
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.)
Next, I tried creating a Pixbuf from the data using Pixbuf.new_from_data()
, but this is buggy too (see gdk-pixbuf bug 674691) (yes, that's me in comment 3).
Then I looked at Cairo: ImageSurface.create_for_data
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 Pixbuf
afterwards and then wrapping that in a gtk.Image
, and it works. But I'm using Python3 (and even then, it's messy - Cairo is a vector graphics library, after all)).
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.
So...any other methods?
Working code
Based on Havok's answer, here's a working example:
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 < 10, j >= 10, (i < 10) ^ (j < 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()
Edit: actually, for correctness, I think this will need a pixels.byteswap()
on little-endian systems before adding to the header (though of course it doesn't matter with these colours).