14

I am looking to see if there is another way to convert a PIL Image to GTK Pixbuf. Right now all I have is what seems to be like inefficient coding practice that I found and hacked to my needs. This is what I have so far:

def image2pixbuf(self,im):  
    file1 = StringIO.StringIO()  
    im.save(file1, "ppm")  
    contents = file1.getvalue()  
    file1.close()  
    loader = gtk.gdk.PixbufLoader("pnm")  
    loader.write(contents, len(contents))  
    pixbuf = loader.get_pixbuf()  
    loader.close()  
    return pixbuf 

Is there some easier way to do this conversion that I missed?

bsktball11ch
  • 763
  • 1
  • 6
  • 6

3 Answers3

13

You can do it efficiently if you go via a numpy array:

import numpy
arr = numpy.array(im)
return gtk.gdk.pixbuf_new_from_array(arr, gtk.gdk.COLORSPACE_RGB, 8)
maxy
  • 4,971
  • 1
  • 23
  • 25
  • 13
    After the migration from PyGtk to PyGI, the return line should probably be: 'return GdkPixbuf.Pixbuf.new_from_data(arr, GdkPixbuf.Colorspace.RGB, False, 8, arr.shape[1], arr.shape[0], arr.shape[1] * 3)' – David Planella Jan 16 '12 at 10:07
9

If you're using PyGI and GTK+3, here's an alternative which also removes the need for a dependency on numpy:

import array
from gi.repository import GdkPixbuf

def image2pixbuf(self,im):
    arr = array.array('B', im.tostring())
    width, height = im.size
    return GdkPixbuf.Pixbuf.new_from_data(arr, GdkPixbuf.Colorspace.RGB,
                                          True, 8, width, height, width * 4)
K3---rnc
  • 6,717
  • 3
  • 31
  • 46
David Planella
  • 2,313
  • 2
  • 25
  • 30
  • Sadly this seems not to be working at the moment, see http://stackoverflow.com/questions/7906814/converting-pil-image-to-gtk-pixbuf – Havok May 11 '12 at 08:23
  • Could you be more specific? Which part does exactly not work? Also, your link points to this current question on stackoverflow. Perhaps you meant to point to another one? – David Planella May 14 '12 at 12:45
  • I'm sorry, I pasted the wrong link: http://stackoverflow.com/questions/10341988/converting-pil-gdkpixbuf/ – Havok May 16 '12 at 17:34
  • 6
    new_from_data() doesn't manage memory correctly, new_from_bytes() was recently added and will be available in 3.14 (https://bugzilla.gnome.org/show_bug.cgi?id=732297). See also: http://stackoverflow.com/questions/24062779/how-to-correctly-covert-3d-array-into-continguous-rgb-bytes/24070152#24070152 – Simon Feltman Aug 29 '14 at 17:12
2

I'm not able to use gtk 3.14 (this version has the method new_from_bytes) [1], so did this workaroud like yours in order to get it working:

from gi.repository import GdkPixbuf
import cv2

def image2pixbuf(im): 
  # convert image from BRG to RGB (pnm uses RGB)
  im2 = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)
  # get image dimensions (depth is not used)
  height, width, depth = im2.shape
  pixl = GdkPixbuf.PixbufLoader.new_with_type('pnm')
  # P6 is the magic number of PNM format, 
  # and 255 is the max color allowed, see [2]
  pixl.write("P6 %d %d 255 " % (width, height) + im2.tostring())
  pix = pixl.get_pixbuf()
  pixl.close()
  return pix

References:

  1. https://bugzilla.gnome.org/show_bug.cgi?id=732297
  2. http://en.wikipedia.org/wiki/Netpbm_format
Community
  • 1
  • 1
iuridiniz
  • 2,213
  • 24
  • 26