1 /* -*- mode: C; c-basic-offset: 4 -*-
2  * C extensions for backend_gdk
3  */
4 
5 #include "Python.h"
6 #include "numpy/arrayobject.h"
7 
8 #include <pygtk/pygtk.h>
9 
10 static PyTypeObject *_PyGdkPixbuf_Type;
11 #define PyGdkPixbuf_Type (*_PyGdkPixbuf_Type)
12 
pixbuf_get_pixels_array(PyObject * self,PyObject * args)13 static PyObject *pixbuf_get_pixels_array(PyObject *self, PyObject *args)
14 {
15     /* 1) read in Python pixbuf, get the underlying gdk_pixbuf */
16     PyGObject *py_pixbuf;
17     GdkPixbuf *gdk_pixbuf;
18     PyArrayObject *array;
19     npy_intp dims[3] = { 0, 0, 3 };
20     npy_intp strides[3];
21 
22     if (!PyArg_ParseTuple(args, "O!:pixbuf_get_pixels_array", &PyGdkPixbuf_Type, &py_pixbuf))
23         return NULL;
24 
25     gdk_pixbuf = GDK_PIXBUF(py_pixbuf->obj);
26 
27     /* 2) same as pygtk/gtk/gdk.c _wrap_gdk_pixbuf_get_pixels_array()
28      * with 'self' changed to py_pixbuf
29      */
30 
31     dims[0] = gdk_pixbuf_get_height(gdk_pixbuf);
32     dims[1] = gdk_pixbuf_get_width(gdk_pixbuf);
33     if (gdk_pixbuf_get_has_alpha(gdk_pixbuf))
34         dims[2] = 4;
35 
36     strides[0] = gdk_pixbuf_get_rowstride(gdk_pixbuf);
37     strides[1] = dims[2];
38     strides[2] = 1;
39 
40     array = (PyArrayObject*)
41         PyArray_New(&PyArray_Type, 3, dims, NPY_UBYTE, strides,
42                     (void*)gdk_pixbuf_get_pixels(gdk_pixbuf), 1,
43                     NPY_ARRAY_WRITEABLE, NULL);
44 
45     if (array == NULL)
46         return NULL;
47 
48     /* the array holds a ref to the pixbuf pixels through this wrapper*/
49     Py_INCREF(py_pixbuf);
50     if (PyArray_SetBaseObject(array, (PyObject *)py_pixbuf) == -1) {
51         Py_DECREF(py_pixbuf);
52         Py_DECREF(array);
53         return NULL;
54     }
55     return PyArray_Return(array);
56 }
57 
58 static PyMethodDef _backend_gdk_functions[] = {
59     { "pixbuf_get_pixels_array", (PyCFunction)pixbuf_get_pixels_array, METH_VARARGS },
60     { NULL, NULL, 0 }
61 };
62 
init_backend_gdk(void)63 PyMODINIT_FUNC init_backend_gdk(void)
64 {
65     PyObject *mod;
66     mod = Py_InitModule("matplotlib.backends._backend_gdk", _backend_gdk_functions);
67     import_array();
68     init_pygtk();
69 
70     mod = PyImport_ImportModule("gtk.gdk");
71     _PyGdkPixbuf_Type = (PyTypeObject *)PyObject_GetAttrString(mod, "Pixbuf");
72 }
73