def test_new_from_data_zero_size(): ''' Attempts to create zero-size pixbufs should raise RuntimeError. :bug: #584769 ''' try: gdk.pixbuf_new_from_data('', gdk.COLORSPACE_RGB, False, 8, 0, 0, 0) assert False except RuntimeError: assert True
def set_icon_from_data(self, pixels, has_alpha, w, h, rowstride, options={}): #use a temporary file (yuk) try: from gtk import gdk except: #no gtk.gdk... no can do return import tempfile try: _, filename = tempfile.mkstemp(suffix="png") log("set_icon_from_data%s using temporary file %s", ("%s pixels" % len(pixels), has_alpha, w, h, rowstride), filename) tray_icon = gdk.pixbuf_new_from_data(pixels, gdk.COLORSPACE_RGB, has_alpha, 8, w, h, rowstride) tray_icon.save(filename, "png") self.do_set_icon_from_file(filename) finally: os.unlink(filename)
def image_from_ndarray(array, format, size = None): """ Creates an Image from a numpy ndarray object. The format may be 'RGB' or 'RGBA'. If a size is specified, the array will be implicitly reshaped to that size, otherwise the size is inferred from the first two dimensions of the array. """ if array.itemsize <> 1: raise ValueError("Color component size must be 1 byte") if size is None: shape = array.shape if len(shape) <> 3: raise ValueError("Array has wrong number of dimensions") width, height, pixel_size = shape if pixel_size <> len(format): raise ValueError("Last dimension of array does not match format") else: width, height = size pixel_size = len(format) data_size = array.size if data_size <> width * height * pixel_size: raise ValueError("Array has wrong shape for specified size and format") alpha = pixel_size == 4 gdk_pixbuf = gdk.pixbuf_new_from_data(array, gdk.COLORSPACE_RGB, alpha, 8, width, height, width * pixel_size) image = Image._from_gdk_pixbuf(gdk_pixbuf) #image._data = array ### return image
def make_cursor(self, cursor_data): #if present, try cursor ny name: if len(cursor_data)>=9 and cursor_names: cursor_name = cursor_data[8] if cursor_name: gdk_cursor = cursor_names.get(cursor_name.upper()) if gdk_cursor is not None: log("setting new cursor by name: %s=%s", cursor_name, gdk_cursor) return gdk.Cursor(gdk_cursor) else: log("cursor name '%s' not found", cursor_name) #create cursor from the pixel data: w, h, xhot, yhot, serial, pixels = cursor_data[2:8] if len(pixels)<w*h*4: import binascii log.warn("not enough pixels provided in cursor data: %s needed and only %s bytes found (%s)", w*h*4, len(pixels), binascii.hexlify(pixels)[:100]) return pixbuf = gdk.pixbuf_new_from_data(pixels, gdk.COLORSPACE_RGB, True, 8, w, h, w * 4) x = max(0, min(xhot, w-1)) y = max(0, min(yhot, h-1)) size = gdk.display_get_default().get_default_cursor_size() log("new cursor at %s,%s with serial=%s, dimensions: %sx%s, len(pixels)=%s, default cursor size is %s", xhot,yhot, serial, w,h, len(pixels), size) if size>0 and (size<w or size<h) and False: ratio = float(max(w,h))/size log("downscaling cursor by %.2f", ratio) pixbuf = pixbuf.scale_simple(int(w/ratio), int(h/ratio), gdk.INTERP_BILINEAR) x = int(x/ratio) y = int(y/ratio) return gdk.Cursor(gdk.display_get_default(), pixbuf, x, y)
def _mkbrushbt(self, frame, brush): if brush.icon: icon_image = gtk.image_new_from_file(brush.icon) pixbuf = icon_image.get_pixbuf() width = pixbuf.get_property('width') height = pixbuf.get_property('height') else: self._drawbrush.set_from_brush(brush) width = 128 height = 60 buf = self._drawbrush.paint_rgb_preview( width, height, fmt=_pixbuf.FORMAT_RGBA8_NOA) pixbuf = gdk.pixbuf_new_from_data(buf, gdk.COLORSPACE_RGB, True, 8, buf.width, buf.height, buf.stride) icon_image = gtk.image_new_from_pixbuf(pixbuf) bt = gtk.ToggleButton() bt.set_image(icon_image) bt.set_size_request(width + 15, height + 5) bt.show_all() bt.connect('clicked', self._on_brush_bt_clicked) bt.connect('button-release-event', self._on_brush_bt_released) bt.brush = brush bt.bt2 = None # button in another page if it has been added t = frame.table x = t.count % TABLE_WIDTH y = t.count / TABLE_WIDTH frame.table.attach(bt, x, x + 1, y, y + 1, gtk.FILL, gtk.FILL, 1, 1) t.count += 1 return bt
def image_from_ndarray(array, format, size=None): """ Creates an Image from a numpy ndarray object. The format may be 'RGB' or 'RGBA'. If a size is specified, the array will be implicitly reshaped to that size, otherwise the size is inferred from the first two dimensions of the array. """ if array.itemsize <> 1: raise ValueError("Color component size must be 1 byte") if size is None: shape = array.shape if len(shape) <> 3: raise ValueError("Array has wrong number of dimensions") width, height, pixel_size = shape if pixel_size <> len(format): raise ValueError("Last dimension of array does not match format") else: width, height = size pixel_size = len(format) data_size = array.size if data_size <> width * height * pixel_size: raise ValueError( "Array has wrong shape for specified size and format") alpha = pixel_size == 4 gdk_pixbuf = gdk.pixbuf_new_from_data(array, gdk.COLORSPACE_RGB, alpha, 8, width, height, width * pixel_size) image = Image._from_gdk_pixbuf(gdk_pixbuf) #image._data = array ### return image
def _do_paint_rgb32(self, img_data, x, y, width, height, rowstride, options): has_alpha = options.boolget( "has_alpha", False) or options.get("rgb_format", "").find("A") >= 0 if has_alpha: img_data = self.unpremultiply(img_data) if isinstance(img_data, (memoryview, _buffer, bytearray)): img_data = memoryview_to_bytes(img_data) if INDIRECT_BGR: img_data, rowstride = self.bgr_to_rgb( img_data, width, height, rowstride, options.strget("rgb_format", ""), "RGBA") if has_alpha: #draw_rgb_32_image does not honour alpha, we have to use pixbuf: pixbuf = gdk.pixbuf_new_from_data(img_data, gdk.COLORSPACE_RGB, True, 8, width, height, rowstride) cr = self._backing.cairo_create() cr.rectangle(x, y, width, height) cr.set_source_pixbuf(pixbuf, x, y) cr.set_operator(cairo.OPERATOR_SOURCE) cr.paint() else: #no alpha or scaling is easier: gc = self._backing.new_gc() self._backing.draw_rgb_32_image(gc, x, y, width, height, gdk.RGB_DITHER_NONE, img_data, rowstride) if self.paint_box_line_width > 0: self.paint_box(x, y, width, height, options) return True
def set_icon_from_data(self, pixels, has_alpha, w, h, rowstride, options={}): tray_icon = gdk.pixbuf_new_from_data(pixels, gdk.COLORSPACE_RGB, has_alpha, 8, w, h, rowstride) self.macapp.set_dock_icon_pixbuf(tray_icon)
def _do_paint_rgb32(self, img_data, x, y, width, height, rowstride, options): #log.info("do_paint_rgb32(%s bytes, %s, %s, %s, %s, %s, %s, %s) backing depth=%s", len(img_data), x, y, width, height, rowstride, options, callbacks, self._backing.get_depth()) #log.info("data head=%s", [hex(ord(v))[2:] for v in list(img_data[:500])]) rgba = self.unpremultiply(img_data) pixbuf = gdk.pixbuf_new_from_data(rgba, gtk.gdk.COLORSPACE_RGB, True, 8, width, height, rowstride) cr = self._backing.cairo_create() cr.rectangle(x, y, width, height) cr.set_source_pixbuf(pixbuf, x, y) cr.set_operator(cairo.OPERATOR_SOURCE) cr.paint() return True
def set_icon_from_data(self, pixels, has_alpha, w, h, rowstride): #TODO: use native code somehow import os from gtk import gdk try: _, filename = tempfile.mkstemp(".ico", "temp") tray_icon = gdk.pixbuf_new_from_data(pixels, gdk.COLORSPACE_RGB, has_alpha, 8, w, h, rowstride) tray_icon.save(filename, "ico") self.set_icon(filename) finally: os.unlink(filename)
def set_icon_from_data(self, pixels, has_alpha, w, h, rowstride): # TODO: use native code somehow import os from gtk import gdk try: _, filename = tempfile.mkstemp(".ico", "temp") tray_icon = gdk.pixbuf_new_from_data(pixels, gdk.COLORSPACE_RGB, has_alpha, 8, w, h, rowstride) tray_icon.save(filename, "ico") self.set_icon(filename) finally: os.unlink(filename)
def make_cursor(self, cursor_data): #if present, try cursor ny name: if len(cursor_data) >= 9 and cursor_names: cursor_name = cursor_data[8] if cursor_name: gdk_cursor = cursor_names.get(cursor_name.upper()) if gdk_cursor is not None: log("setting new cursor by name: %s=%s", cursor_name, gdk_cursor) return gdk.Cursor(gdk_cursor) else: global missing_cursor_names if cursor_name not in missing_cursor_names: log.warn("cursor name '%s' not found", cursor_name) missing_cursor_names.add(cursor_name) #create cursor from the pixel data: w, h, xhot, yhot, serial, pixels = cursor_data[2:8] if len(pixels) < w * h * 4: import binascii log.warn( "not enough pixels provided in cursor data: %s needed and only %s bytes found (%s)", w * h * 4, len(pixels), binascii.hexlify(pixels)[:100]) return pixbuf = gdk.pixbuf_new_from_data(pixels, gdk.COLORSPACE_RGB, True, 8, w, h, w * 4) x = max(0, min(xhot, w - 1)) y = max(0, min(yhot, h - 1)) display = gdk.display_get_default() csize = display.get_default_cursor_size() cmaxw, cmaxh = display.get_maximal_cursor_size() if len(cursor_data) >= 11: ssize = cursor_data[9] smax = cursor_data[10] log("server cursor sizes: default=%s, max=%s", ssize, smax) log( "new cursor at %s,%s with serial=%s, dimensions: %sx%s, len(pixels)=%s, default cursor size is %s, maximum=%s", xhot, yhot, serial, w, h, len(pixels), csize, (cmaxw, cmaxh)) ratio = 1 if w > cmaxw or h > cmaxh or (csize > 0 and (csize < w or csize < h)): ratio = max( float(w) / cmaxw, float(h) / cmaxh, float(max(w, h)) / csize) log("downscaling cursor by %.2f", ratio) pixbuf = pixbuf.scale_simple(int(w / ratio), int(h / ratio), gdk.INTERP_BILINEAR) x = int(x / ratio) y = int(y / ratio) return gdk.Cursor(gdk.display_get_default(), pixbuf, x, y)
def set_icon_from_data(self, pixels, has_alpha, w, h, rowstride): #use a temporary file (yuk) try: from gtk import gdk except: #no gtk.gdk... no can do return import tempfile try: _, filename = tempfile.mkstemp(suffix="png") debug("set_icon_from_data%s using temporary file %s", ("%s pixels" % len(pixels), has_alpha, w, h, rowstride), filename) tray_icon = gdk.pixbuf_new_from_data(pixels, gdk.COLORSPACE_RGB, has_alpha, 8, w, h, rowstride) tray_icon.save(filename, "png") self.do_set_icon_from_file(filename) finally: os.unlink(filename)
def draw_to_pixbuf(p, z, r, sel=None): w, h = p.get_size() zs = zooms[z] m = zoom_rot_matrix(w, h, zs, r) zw, zh = zoomed(w, zs), zoomed(h, zs) if r == 1 or r == 3: zw, zh = zh, zw st = get_row_stride(zw) surf = C.ImageSurface(FMT, zw, zh) c = PopplerCtx(surf) with drawingto(c): c.set_source_rgb(1, 1, 1).rectangle(0, 0, zw, zh).fill() c.set_matrix(m).page(p, sel) pixels = surf.get_data() changesex(pixels) return GG.pixbuf_new_from_data(pixels, CSP, True, 8, zw, zh, st)
def image_from_pil_image(pil_image): """Creates an Image from a Python Imaging Library (PIL) Image object.""" mode = pil_image.mode w, h = pil_image.size data = pil_image.tostring() if mode == "RGB": bps = 3; alpha = False elif mode == "RGBA": bps = 4; alpha = True else: raise ValueError("Unsupported PIL image mode '%s'" % mode) bpr = w * bps image = Image.__new__(Image) image._gdk_pixbuf = gdk.pixbuf_new_from_data(data, COLORSPACE_RGB, alpha, 8, w, h, bpr) return image
def _do_paint_rgb32(self, img_data, x, y, width, height, rowstride, options, callbacks): #log.debug("do_paint_rgb32(%s bytes, %s, %s, %s, %s, %s, %s, %s) backing depth=%s", len(img_data), x, y, width, height, rowstride, options, callbacks, self._backing.get_depth()) #log.info("data head=%s", [hex(ord(v))[2:] for v in list(img_data[:500])]) if self._backing is None: return False from xpra.codecs.argb.argb import unpremultiply_argb, unpremultiply_argb_in_place, byte_buffer_to_buffer #@UnresolvedImport if type(img_data)==str or not hasattr(img_data, "raw"): #cannot do in-place: img_data = byte_buffer_to_buffer(unpremultiply_argb(img_data)) else: #assume this is a writeable buffer (ie: ctypes from mmap): unpremultiply_argb_in_place(img_data) pixbuf = gdk.pixbuf_new_from_data(img_data, gtk.gdk.COLORSPACE_RGB, True, 8, width, height, rowstride) cr = self._backing.cairo_create() cr.rectangle(x, y, width, height) cr.set_source_pixbuf(pixbuf, x, y) cr.set_operator(cairo.OPERATOR_SOURCE) cr.paint() return True
def image_from_pil_image(pil_image): """Creates an Image from a Python Imaging Library (PIL) Image object.""" mode = pil_image.mode w, h = pil_image.size data = pil_image.tostring() if mode == "RGB": bps = 3 alpha = False elif mode == "RGBA": bps = 4 alpha = True else: raise ValueError("Unsupported PIL image mode '%s'" % mode) bpr = w * bps image = Image.__new__(Image) image._gdk_pixbuf = gdk.pixbuf_new_from_data(data, COLORSPACE_RGB, alpha, 8, w, h, bpr) return image
def _do_paint_rgb32(self, img_data, x, y, width, height, rowstride, options): has_alpha = options.boolget("has_alpha", False) or options.get("rgb_format", "").find("A")>=0 if has_alpha: img_data = self.unpremultiply(img_data) img_data = memoryview_to_bytes(img_data) if INDIRECT_BGR: img_data, rowstride = self.bgr_to_rgb(img_data, width, height, rowstride, options.strget("rgb_format", ""), "RGBA") if has_alpha: #draw_rgb_32_image does not honour alpha, we have to use pixbuf: pixbuf = gdk.pixbuf_new_from_data(img_data, gdk.COLORSPACE_RGB, True, 8, width, height, rowstride) cr = self._backing.cairo_create() cr.rectangle(x, y, width, height) cr.set_source_pixbuf(pixbuf, x, y) cr.set_operator(cairo.OPERATOR_SOURCE) cr.paint() else: #no alpha or scaling is easier: gc = self._backing.new_gc() self._backing.draw_rgb_32_image(gc, x, y, width, height, gdk.RGB_DITHER_NONE, img_data, rowstride) return True
def refresh_brush(self, bt): bt = bt.allbt brush = bt.brush self._drawbrush.set_from_brush(brush) width = 128 height = 60 buf = self._drawbrush.paint_rgb_preview(width, height, fmt=_pixbuf.FORMAT_RGBA8_NOA) pixbuf = gdk.pixbuf_new_from_data(buf, gdk.COLORSPACE_RGB, True, 8, buf.width, buf.height, buf.stride) icon_image = gtk.image_new_from_pixbuf(pixbuf) bt.set_image(icon_image) bt.set_size_request(width + 15, height + 5) if bt.bt2: bt.bt2.set_image(icon_image) bt.bt2.set_size_request(width + 15, height + 5) bt.show_all()
def _do_paint_rgb32(self, img_data, x, y, width, height, rowstride, options, callbacks): #log.debug("do_paint_rgb32(%s bytes, %s, %s, %s, %s, %s, %s, %s) backing depth=%s", len(img_data), x, y, width, height, rowstride, options, callbacks, self._backing.get_depth()) #log.info("data head=%s", [hex(ord(v))[2:] for v in list(img_data[:500])]) if self._backing is None: return False from xpra.codecs.argb.argb import unpremultiply_argb, unpremultiply_argb_in_place, byte_buffer_to_buffer #@UnresolvedImport if type(img_data) == str or not hasattr(img_data, "raw"): #cannot do in-place: img_data = byte_buffer_to_buffer(unpremultiply_argb(img_data)) else: #assume this is a writeable buffer (ie: ctypes from mmap): unpremultiply_argb_in_place(img_data) pixbuf = gdk.pixbuf_new_from_data(img_data, gtk.gdk.COLORSPACE_RGB, True, 8, width, height, rowstride) cr = self._backing.cairo_create() cr.rectangle(x, y, width, height) cr.set_source_pixbuf(pixbuf, x, y) cr.set_operator(cairo.OPERATOR_SOURCE) cr.paint() return True
def draw_on_canvas(self,widget,time): #create pixbuf to store data from iplimage #image processing part frame=cv.QueryFrame(cap) print frame cv.CvtColor(frame,frame,cv.CV_BGR2RGB) cv.Flip(frame,frame,1) print "copying to pixbuff..." pixbuf=gdk.pixbuf_new_from_data(frame.tostring(),gdk.COLORSPACE_RGB,False,frame.depth,frame.width,frame.height,1500) print pixbuf display=self.canvas.window img=gdk.Image(gdk.IMAGE_FASTEST,display.get_visual(),640,480) print display #display.draw_image(display.new_gc(),img,0,0,0,0,-1,-1) display.draw_rgb_image(display.new_gc(),0,0,640,480,gdk.RGB_DITHER_NONE,frame.tostring(),1920) print "drawing...." return True
def make_cursor(self, cursor_data): #if present, try cursor ny name: if len(cursor_data)>=9 and cursor_names: cursor_name = cursor_data[8] if cursor_name: gdk_cursor = cursor_names.get(cursor_name.upper()) if gdk_cursor is not None: log("setting new cursor by name: %s=%s", cursor_name, gdk_cursor) return gdk.Cursor(gdk_cursor) else: global missing_cursor_names if cursor_name not in missing_cursor_names: log.warn("cursor name '%s' not found", cursor_name) missing_cursor_names.add(cursor_name) #create cursor from the pixel data: w, h, xhot, yhot, serial, pixels = cursor_data[2:8] if len(pixels)<w*h*4: import binascii log.warn("not enough pixels provided in cursor data: %s needed and only %s bytes found (%s)", w*h*4, len(pixels), binascii.hexlify(pixels)[:100]) return pixbuf = gdk.pixbuf_new_from_data(pixels, gdk.COLORSPACE_RGB, True, 8, w, h, w * 4) x = max(0, min(xhot, w-1)) y = max(0, min(yhot, h-1)) display = gdk.display_get_default() csize = display.get_default_cursor_size() cmaxw, cmaxh = display.get_maximal_cursor_size() if len(cursor_data)>=11: ssize = cursor_data[9] smax = cursor_data[10] log("server cursor sizes: default=%s, max=%s", ssize, smax) log("new cursor at %s,%s with serial=%s, dimensions: %sx%s, len(pixels)=%s, default cursor size is %s, maximum=%s", xhot,yhot, serial, w,h, len(pixels), csize, (cmaxw, cmaxh)) ratio = 1 if w>cmaxw or h>cmaxh or (csize>0 and (csize<w or csize<h)): ratio = max(float(w)/cmaxw, float(h)/cmaxh, float(max(w,h))/csize) log("downscaling cursor by %.2f", ratio) pixbuf = pixbuf.scale_simple(int(w/ratio), int(h/ratio), gdk.INTERP_BILINEAR) x = int(x/ratio) y = int(y/ratio) return gdk.Cursor(gdk.display_get_default(), pixbuf, x, y)
def make_cursor(self, cursor_data): #if present, try cursor ny name: if len(cursor_data) >= 9 and cursor_names: cursor_name = cursor_data[8] if cursor_name: gdk_cursor = cursor_names.get(cursor_name.upper()) if gdk_cursor is not None: log("setting new cursor by name: %s=%s", cursor_name, gdk_cursor) return gdk.Cursor(gdk_cursor) else: log("cursor name '%s' not found", cursor_name) #create cursor from the pixel data: w, h, xhot, yhot, serial, pixels = cursor_data[2:8] if len(pixels) < w * h * 4: import binascii log.warn( "not enough pixels provided in cursor data: %s needed and only %s bytes found (%s)", w * h * 4, len(pixels), binascii.hexlify(pixels)[:100]) return pixbuf = gdk.pixbuf_new_from_data(pixels, gdk.COLORSPACE_RGB, True, 8, w, h, w * 4) x = max(0, min(xhot, w - 1)) y = max(0, min(yhot, h - 1)) size = gdk.display_get_default().get_default_cursor_size() log( "new cursor at %s,%s with serial=%s, dimensions: %sx%s, len(pixels)=%s, default cursor size is %s", xhot, yhot, serial, w, h, len(pixels), size) if size > 0 and (size < w or size < h) and False: ratio = float(max(w, h)) / size log("downscaling cursor by %.2f", ratio) pixbuf = pixbuf.scale_simple(int(w / ratio), int(h / ratio), gdk.INTERP_BILINEAR) x = int(x / ratio) y = int(y / ratio) return gdk.Cursor(gdk.display_get_default(), pixbuf, x, y)
def set_windows_cursor(self, gtkwindows, new_cursor): cursor = None if len(new_cursor)>0: cursor = None if len(new_cursor)>=9 and cursor_names: cursor_name = new_cursor[8] if cursor_name: gdk_cursor = cursor_names.get(cursor_name.upper()) if gdk_cursor is not None: try: from xpra.x11.gtk_x11.error import trap log("setting new cursor: %s=%s", cursor_name, gdk_cursor) cursor = trap.call_synced(gdk.Cursor, gdk_cursor) except: pass if cursor is None: w, h, xhot, yhot, serial, pixels = new_cursor[2:8] log("new cursor at %s,%s with serial=%s, dimensions: %sx%s, len(pixels)=%s" % (xhot,yhot, serial, w,h, len(pixels))) pixbuf = gdk.pixbuf_new_from_data(pixels, gdk.COLORSPACE_RGB, True, 8, w, h, w * 4) x = max(0, min(xhot, w-1)) y = max(0, min(yhot, h-1)) size = gdk.display_get_default().get_default_cursor_size() if size>0 and (size<w or size<h): ratio = float(max(w,h))/size pixbuf = pixbuf.scale_simple(int(w/ratio), int(h/ratio), gdk.INTERP_BILINEAR) x = int(x/ratio) y = int(y/ratio) cursor = gdk.Cursor(gdk.display_get_default(), pixbuf, x, y) for gtkwindow in gtkwindows: if gtk.gtk_version>=(2,14): gdkwin = gtkwindow.get_window() else: gdkwin = gtkwindow.window #trays don't have a gdk window if gdkwin: gdkwin.set_cursor(cursor)
def save_pixels_to_png(pixels, width, height, filename): """Save raw pixels to a PNG file through pixbuf and PyGTK.""" gdk.pixbuf_new_from_data(pixels, gdk.COLORSPACE_RGB, True, 8, width, height, width * 4).save(filename, 'png')
def set_color(self, color): pass #return self._font.set_color(color) def __getattr__(self, attr): if attr in ("ascent", "descent", "max_ascent", "max_descent"): return None return super(Font, self).__getattr__(attr) def open(file): return Image(file) def new((w, h), rawdata = None, from_format = "BGRA"): if from_format not in get_capabilities()["from-raw-formats"]: raise ValueError, "Unsupported raw format: %s" % from_format if rawdata: has_alpha, bpp = { "RGBA": (True, 4), "RGB": (False, 3) } [from_format] return Image( gdk.pixbuf_new_from_data(rawdata, gdk.COLORSPACE_RGB, has_alpha, 8, w, h, w*bpp) ) else: return Image( gdk.Pixbuf(gdk.COLORSPACE_RGB, True, 8, w, h) ) def add_font_path(path): pass def load_font(font, size): pass
def save_pixels_to_png(pixels, width, height, filename): """Save raw pixels to a PNG file through pixbuf and PyGTK.""" gdk.pixbuf_new_from_data( pixels, 'rgb', False, 8, width, height, width * 3 ).save(filename, 'png')
def save_pixels_to_png(pixels, width, height, filename): """Save raw pixels to a PNG file through pixbuf and PyGTK.""" gdk.pixbuf_new_from_data( pixels, gdk.COLORSPACE_RGB, True, 8, width, height, width * 4 ).save(filename, 'png')