/* -*- Mode: C; c-basic-offset: 4 -*- * pygtk- Python bindings for the GTK toolkit. * Copyright (C) 1998-2003 James Henstridge * * gdkpixbuf.override: gtk.gdk.Pixbuf and gtk.gdk.PixbufLoader overrides * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA */ %% override gdk_pixbuf_render_pixmap_and_mask kwargs static PyObject * _wrap_gdk_pixbuf_render_pixmap_and_mask(PyGObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "alpha_threshold", NULL}; int alpha_threshold = 127; GdkPixmap *pixmap; GdkBitmap *mask; PyObject *pypixmap, *pymask, *ret; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:GdkPixbuf.render_pixmap_and_mask", kwlist, &alpha_threshold)) return NULL; gdk_pixbuf_render_pixmap_and_mask(GDK_PIXBUF(self->obj), &pixmap, &mask, alpha_threshold); if (pixmap) { pypixmap = pygobject_new((GObject *) pixmap); g_object_unref(pixmap); } else { Py_INCREF(Py_None); pypixmap = Py_None; } if (mask) { pymask = pygobject_new((GObject *) mask); gdk_bitmap_unref(mask); } else { Py_INCREF(Py_None); pymask = Py_None; } ret = Py_BuildValue("(NN)", pypixmap, pymask); return ret; } %% override-attr GdkPixbuf.pixel_array #ifdef HAVE_NUMPY static int have_numpy(void) { /* Return 1 if Numeric is available, return 0 and set and exception if it is not. */ static int import_done = 0; static PyObject *exc_type=NULL, *exc_value=NULL; PyObject *exc_tb=NULL; if (exc_type != NULL) { PyErr_Restore(exc_type, exc_value, NULL); return 0; } if (!import_done) { import_done = 1; import_array1(1); if (PyErr_Occurred()) { PyErr_Fetch(&exc_type, &exc_value, &exc_tb); Py_INCREF(exc_type); Py_XINCREF(exc_value); PyErr_Restore(exc_type, exc_value, exc_tb); return 0; } } return 1; } #endif static PyObject * _wrap_gdk_pixbuf__get_pixel_array(PyGObject *self, void *closure) { PyErr_Warn(PyExc_DeprecationWarning, "use pixbuf.get_pixels_array() instead of the pixbuf.pixel_array attribute"); return _wrap_gdk_pixbuf_get_pixels_array(self); } %% define GdkPixbuf.get_pixels_array noargs static PyObject * _wrap_gdk_pixbuf_get_pixels_array(PyGObject *self) { #ifdef HAVE_NUMPY GdkPixbuf *pixbuf = GDK_PIXBUF(self->obj); PyArrayObject *array; int dims[3] = { 0, 0, 3 }; if (!have_numpy()) return NULL; dims[0] = gdk_pixbuf_get_height(pixbuf); dims[1] = gdk_pixbuf_get_width(pixbuf); if (gdk_pixbuf_get_has_alpha(pixbuf)) dims[2] = 4; array = (PyArrayObject *)PyArray_FromDimsAndData(3, dims, PyArray_UBYTE, (char *)gdk_pixbuf_get_pixels(pixbuf)); if (array == NULL) return NULL; array->strides[0] = gdk_pixbuf_get_rowstride(pixbuf); /* the array holds a ref to the pixbuf pixels through this wrapper*/ Py_INCREF(self); array->base = (PyObject *)self; return PyArray_Return(array); #else PyErr_SetString(PyExc_RuntimeError, "pygtk was not compiled with Numeric Python support"); return NULL; #endif } %% override gdk_pixbuf_get_pixels noargs static PyObject * _wrap_gdk_pixbuf_get_pixels(PyGObject *self) { GdkPixbuf *pixbuf; guchar *pixels; gint rowstride, height; pixbuf = GDK_PIXBUF(self->obj); pixels = gdk_pixbuf_get_pixels(pixbuf); rowstride = gdk_pixbuf_get_rowstride(pixbuf); height = gdk_pixbuf_get_height(pixbuf); if (pixels == NULL) { PyErr_SetString(PyExc_ValueError, "could not get pixel data"); return NULL; } return PyString_FromStringAndSize((char*)pixels, rowstride*height); } %% override gdk_pixbuf_save kwargs static PyObject * _wrap_gdk_pixbuf_save(PyGObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"filename", "type", "options", NULL}; gchar *filename, *type, **option_keys = NULL, **option_values = NULL; PyObject *py_options = NULL; GError *error = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|O!:GdkPixbuf.save", kwlist, &filename, &type, &PyDict_Type, &py_options)) return NULL; if (py_options != NULL) { guint len; Py_ssize_t pos = 0, i = 0; PyObject *key, *value; len = PyDict_Size(py_options); option_keys = g_new(gchar *, len + 1); option_values = g_new(gchar *, len + 1); while (PyDict_Next(py_options, &pos, &key, &value)) { if (!PyString_Check(key) || !PyString_Check(value)) { g_free(option_keys); g_free(option_values); PyErr_SetString(PyExc_TypeError, "keys and values must be strings"); return NULL; } option_keys[i] = PyString_AsString(key); option_values[i] = PyString_AsString(value); i++; } option_keys[len] = NULL; option_values[len] = NULL; } pyg_begin_allow_threads; gdk_pixbuf_savev(GDK_PIXBUF(self->obj), filename, type, option_keys, option_values, &error); pyg_end_allow_threads; g_free(option_keys); g_free(option_values); if (pyg_error_check(&error)) return NULL; Py_INCREF(Py_None); return Py_None; } %% override gdk_pixbuf_save_to_callback kwargs typedef struct { PyObject *callback; PyObject *user_data; } py_pixbuf_save_callback_data_t; static gboolean pixbuf_save_func(const gchar *buf, gsize count, GError **error, py_pixbuf_save_callback_data_t *data) { PyObject *ret; if (data->user_data) ret = PyObject_CallFunction(data->callback, "s#O", buf, (Py_ssize_t) count, data->user_data); else ret = PyObject_CallFunction(data->callback, "s#", buf, (Py_ssize_t) count); if (ret == NULL) { PyErr_Print(); return FALSE; } Py_DECREF(ret); return TRUE; } static PyObject * _wrap_gdk_pixbuf_save_to_callback(PyGObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"save_func", "type", "options", "user_data", NULL}; gchar *type, **option_keys = NULL, **option_values = NULL; PyObject *py_options = NULL; GError *error = NULL; py_pixbuf_save_callback_data_t data = { NULL, NULL }; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Os|O!O:GdkPixbuf.save", kwlist, &data.callback, &type, &PyDict_Type, &py_options, &data.user_data)) return NULL; if (!PyCallable_Check(data.callback)) { PyErr_SetString(PyExc_TypeError, "first argument must be callable"); return NULL; } if (py_options != NULL) { Py_ssize_t len; Py_ssize_t pos = 0, i = 0; PyObject *key, *value; len = PyDict_Size(py_options); option_keys = g_new(gchar *, len + 1); option_values = g_new(gchar *, len + 1); while (PyDict_Next(py_options, &pos, &key, &value)) { if (!PyString_Check(key) || !PyString_Check(value)) { g_free(option_keys); g_free(option_values); PyErr_SetString(PyExc_TypeError, "keys and values must be strings"); return NULL; } option_keys[i] = PyString_AsString(key); option_values[i] = PyString_AsString(value); i++; } option_keys[len] = NULL; option_values[len] = NULL; } gdk_pixbuf_save_to_callbackv(GDK_PIXBUF(self->obj), (GdkPixbufSaveFunc) pixbuf_save_func, &data, type, option_keys, option_values, &error); g_free(option_keys); g_free(option_values); if (pyg_error_check(&error)) return NULL; Py_INCREF(Py_None); return Py_None; } %% override gdk_pixbuf_new_from_data kwargs static PyObject * _wrap_gdk_pixbuf_new_from_data(PyObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "data", "colorspace", "has_alpha", "bits_per_sample", "width", "height", "rowstride", NULL }; const gchar *data; GdkColorspace colorspace; gboolean has_alpha; Py_ssize_t data_len; gint bits_per_sample, width, height, rowstride; Py_ssize_t required_len; guchar *data_copy; GdkPixbuf *pixbuf; PyObject *ret; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#iiiiii:pixbuf_new_from_data", kwlist, &data, &data_len, &colorspace, &has_alpha, &bits_per_sample, &width, &height, &rowstride)) return NULL; required_len = height*rowstride; if (data_len < required_len) { PyErr_Format(PyExc_ValueError, "data length (%ld) is less then required by the other parameters (%ld)", (long int) data_len, (long int) required_len); return NULL; } data_copy = g_try_malloc(required_len); if (!data_copy) return PyErr_NoMemory(); memcpy(data_copy, data, required_len); pixbuf = gdk_pixbuf_new_from_data(data_copy, colorspace, has_alpha, bits_per_sample, width, height, rowstride, (GdkPixbufDestroyNotify )g_free, NULL); ret = pygobject_new((GObject *)pixbuf); g_object_unref(pixbuf); return ret; } %% override gdk_pixbuf_new_from_array kwargs static PyObject * _wrap_gdk_pixbuf_new_from_array(PyObject *self, PyObject *args, PyObject *kwargs) { #ifdef HAVE_NUMPY static char *kwlist[] = { "array", "colorspace", "bits_per_sample", NULL }; PyArrayObject *array; GdkColorspace colorspace; gint bits_per_sample ; GdkPixbuf *pixbuf; PyObject *ret; gboolean has_alpha; gint width, height; gint i, j, nc, rs, st0, st1, st2; guchar *src, *dst; if (!have_numpy()) return NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!ii:pixbuf_new_from_array", kwlist, &PyArray_Type, &array, &colorspace, &bits_per_sample)) return NULL; if (array->descr->type_num != PyArray_CHAR && array->descr->type_num != PyArray_UBYTE) { PyErr_SetString(PyExc_TypeError, "array type must be 'c' or 'b'"); return NULL; } if (array->nd != 3 || array->dimensions[2] < 3 || array->dimensions[2] > 4) { PyErr_SetString(PyExc_TypeError, "array shape must be (n,m,3) or (n,m,4)"); return NULL; } height = array->dimensions[0]; width = array->dimensions[1]; has_alpha = array->dimensions[2] == 4; pixbuf = gdk_pixbuf_new(colorspace, has_alpha, bits_per_sample, width, height); src = (guchar*) array->data; dst = gdk_pixbuf_get_pixels(pixbuf); nc = gdk_pixbuf_get_n_channels(pixbuf); rs = gdk_pixbuf_get_rowstride(pixbuf); st0 = array->strides[0]; st1 = array->strides[1]; st2 = array->strides[2]; if (has_alpha) { for (j = 0; j < height; j++) { for (i = 0; i < width; i++) { dst[j*rs + i*4 + 0] = src[j*st0 + i*st1 + 0*st2]; dst[j*rs + i*4 + 1] = src[j*st0 + i*st1 + 1*st2]; dst[j*rs + i*4 + 2] = src[j*st0 + i*st1 + 2*st2]; dst[j*rs + i*4 + 3] = src[j*st0 + i*st1 + 3*st2]; } } } else { for (j = 0; j < height; j++) { for (i = 0; i < width; i++) { dst[j*rs + i*3 + 0] = src[j*st0 + i*st1 + 0*st2]; dst[j*rs + i*3 + 1] = src[j*st0 + i*st1 + 1*st2]; dst[j*rs + i*3 + 2] = src[j*st0 + i*st1 + 2*st2]; } } } ret = pygobject_new((GObject *)pixbuf); g_object_unref(pixbuf); return ret; #else PyErr_SetString(PyExc_RuntimeError, "pygtk was not compiled with Numeric Python support"); return NULL; #endif } %% override gdk_pixbuf_new_from_xpm_data kwargs static PyObject * _wrap_gdk_pixbuf_new_from_xpm_data(PyObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "data", NULL }; PyObject *py_data, *ret; gchar **data; int len, i; GdkPixbuf *pixbuf; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!:pixbuf_new_from_xpm_data", kwlist, &PyList_Type, &py_data)) return NULL; len = PyList_Size(py_data); data = g_new(gchar *, len); for (i = 0; i < len; i ++) { PyObject *item = PyList_GetItem(py_data, i); if (!PyString_Check(item)) { PyErr_SetString(PyExc_TypeError, "data items must be strings"); g_free(data); return NULL; } data[i] = PyString_AsString(item); } pixbuf = gdk_pixbuf_new_from_xpm_data((const char**)data); g_free(data); if (pixbuf == NULL) { PyErr_SetString(PyExc_IOError, "can't load pixbuf"); return NULL; } ret = pygobject_new((GObject *)pixbuf); g_object_unref(pixbuf); return ret; } %% override gdk_pixbuf_loader_new_with_type kwargs static int _wrap_gdk_pixbuf_loader_new_with_type(PyGObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "image_type", NULL }; char *image_type = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s:GdkPixbufLoader.__init__", kwlist, &image_type)) return -1; if (image_type == NULL) { self->obj = (GObject *)gdk_pixbuf_loader_new(); } else { GError *error = NULL; self->obj = (GObject *)gdk_pixbuf_loader_new_with_type(image_type, &error); if (pyg_error_check(&error)) return -1; } if (!self->obj) { PyErr_SetString(PyExc_RuntimeError, "could not create GdkPixbufLoader object"); return -1; } pygobject_register_wrapper((PyObject *)self); return 0; } %% override gdk_pixbuf_loader_write kwargs static PyObject * _wrap_gdk_pixbuf_loader_write(PyGObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "buf", "count", NULL }; Py_ssize_t buf_len; int count = -1, ret; guchar *buf; GError *error = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|i:GdkPixbufLoader.write", kwlist, &buf, &buf_len, &count)) return NULL; if (count < 0 || count > buf_len) { count = buf_len; } ret = gdk_pixbuf_loader_write(GDK_PIXBUF_LOADER(self->obj), buf, count, &error); if (pyg_error_check(&error)) return NULL; return PyBool_FromLong(ret); } %% override gdk_pixbuf_animation_get_iter kwargs static PyObject * _wrap_gdk_pixbuf_animation_get_iter(PyGObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "start_time", NULL }; GdkPixbufAnimationIter *ret; double start_time = 0.0; GTimeVal starttime, *starttimep; PyObject *pyretval; if (!PyArg_ParseTupleAndKeywords( args, kwargs, "|d:GdkPixbufAnimation.get_iter", kwlist, &start_time)) return NULL; if (start_time > 0.0) { starttime.tv_sec = (glong) start_time; starttime.tv_usec = (glong)((start_time - starttime.tv_sec) * G_USEC_PER_SEC); starttimep = &starttime; } else if (start_time == 0.0) { starttimep = NULL; } else { PyErr_SetString(PyExc_ValueError, "start_time must be >= 0.0"); return NULL; } ret = gdk_pixbuf_animation_get_iter(GDK_PIXBUF_ANIMATION(self->obj), starttimep); /* pygobject_new handles NULL checking */ pyretval = pygobject_new((GObject *)ret); if (ret) g_object_unref(ret); return pyretval; } %% override gdk_pixbuf_animation_iter_advance kwargs static PyObject * _wrap_gdk_pixbuf_animation_iter_advance(PyGObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "current_time", NULL }; gboolean ret; double current_time = 0.0; GTimeVal currenttime, *currenttimep; if (!PyArg_ParseTupleAndKeywords( args, kwargs, "|d:GdkPixbufAnimationIter.advance", kwlist, ¤t_time)) return NULL; if (current_time > 0.0) { currenttime.tv_sec = (glong) current_time; currenttime.tv_usec = (glong)((current_time - currenttime.tv_sec) * G_USEC_PER_SEC); currenttimep = ¤ttime; } else if (current_time == 0.0) { currenttimep = NULL; } else { PyErr_SetString(PyExc_ValueError, "current_time must be >= 0.0"); return NULL; } ret = gdk_pixbuf_animation_iter_advance(GDK_PIXBUF_ANIMATION_ITER(self->obj), currenttimep); return PyBool_FromLong(ret); } %% override gdk_pixbuf_get_formats noargs static PyObject * pygtk_make_pixbuf_format_dict(GdkPixbufFormat *format) { PyObject *item, *value; gchar *sval, **aval; gint i; item = PyDict_New(); sval = gdk_pixbuf_format_get_name(format); value = PyString_FromString(sval); PyDict_SetItemString(item, "name", value); Py_DECREF(value); g_free(sval); sval = gdk_pixbuf_format_get_description(format); value = PyString_FromString(sval); PyDict_SetItemString(item, "description", value); Py_DECREF(value); g_free(sval); aval = gdk_pixbuf_format_get_mime_types(format); value = PyList_New(0); for (i = 0; aval[i] != NULL; i++) { PyObject *string_item = PyString_FromString(aval[i]); PyList_Append(value, string_item); Py_DECREF(string_item); } PyDict_SetItemString(item, "mime_types", value); Py_DECREF(value); g_strfreev(aval); aval = gdk_pixbuf_format_get_extensions(format); value = PyList_New(0); for (i = 0; aval[i] != NULL; i++) { PyObject *string_item = PyString_FromString(aval[i]); PyList_Append(value, string_item); Py_DECREF(string_item); } PyDict_SetItemString(item, "extensions", value); Py_DECREF(value); g_strfreev(aval); PyDict_SetItemString(item, "is_writable", PyBool_FromLong(gdk_pixbuf_format_is_writable(format))); return item; } static PyObject * _wrap_gdk_pixbuf_get_formats(PyObject *self) { GSList *list, *tmp; PyObject *ret; list = gdk_pixbuf_get_formats(); ret = PyList_New(0); for (tmp = list; tmp != NULL; tmp = tmp->next) { PyObject *item; item = pygtk_make_pixbuf_format_dict((GdkPixbufFormat *)(tmp->data)); PyList_Append(ret, item); Py_DECREF(item); } g_slist_free(list); return ret; } %% override gdk_pixbuf_fill kwargs static PyObject * _wrap_gdk_pixbuf_fill(PyGObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "pixel", NULL }; PyObject *py_pixel = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:GdkPixbuf.fill", kwlist, &py_pixel)) return NULL; if (PyInt_Check(py_pixel)) gdk_pixbuf_fill(GDK_PIXBUF(self->obj), PyInt_AsLong(py_pixel)); else if (PyLong_Check(py_pixel)) gdk_pixbuf_fill(GDK_PIXBUF(self->obj), PyLong_AsUnsignedLong(py_pixel)); else { PyErr_SetString(PyExc_TypeError, "pixel must be an int or a long"); return NULL; } Py_INCREF(Py_None); return Py_None; } %% override gdk_pixbuf_get_file_info kwargs static PyObject * _wrap_gdk_pixbuf_get_file_info(PyObject *self, PyObject *args, PyObject *kwargs) { PyObject *pygtk_make_pixbuf_format_dict(GdkPixbufFormat *format); static char *kwlist[] = { "filename", NULL }; gint width, height; GdkPixbufFormat *format; gchar *filename; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s:gtk.gdk.pixbuf_get_file_info", kwlist, &filename)) return NULL; format = gdk_pixbuf_get_file_info(filename, &width, &height); if (format) { PyObject *py_format; py_format = pygtk_make_pixbuf_format_dict(format); return Py_BuildValue("(Nii)", py_format, width, height); } Py_INCREF(Py_None); return Py_None; } %% override gdk_pixbuf_loader_get_format noargs static PyObject *pygtk_make_pixbuf_format_dict(GdkPixbufFormat *format); static PyObject * _wrap_gdk_pixbuf_loader_get_format(PyGObject *self) { GdkPixbufFormat *format; format = gdk_pixbuf_loader_get_format(GDK_PIXBUF_LOADER(self->obj)); if (format) return pygtk_make_pixbuf_format_dict(format); Py_INCREF(Py_None); return Py_None; } %% override gdk_pixbuf_get_from_drawable2 kwargs static PyObject * _wrap_gdk_pixbuf_get_from_drawable2(PyObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "pixbuf", "src", "cmap", "src_x", "src_y", "dest_x", "dest_y", "width", "height", NULL }; PyGObject *py_pixbuf, *src, *cmap; int src_x, src_y, dest_x, dest_y, width, height; GdkPixbuf *pixbuf = NULL, *ret; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO!O!iiiiii:pixbuf_get_from_drawable", kwlist, &py_pixbuf, &PyGdkDrawable_Type, &src, &PyGdkColormap_Type, &cmap, &src_x, &src_y, &dest_x, &dest_y, &width, &height)) return NULL; if (py_pixbuf && pygobject_check(py_pixbuf, &PyGdkPixbuf_Type)) pixbuf = GDK_PIXBUF(py_pixbuf->obj); else if ((PyObject *)py_pixbuf != Py_None) { PyErr_SetString(PyExc_TypeError, "pixbuf should be a GdkPixbuf or None"); return NULL; } ret = gdk_pixbuf_get_from_drawable(pixbuf, GDK_DRAWABLE(src->obj), GDK_COLORMAP(cmap->obj), src_x, src_y, dest_x, dest_y, width, height); /* pygobject_new handles NULL checking */ return pygobject_new((GObject *)ret); } %% override gdk_pixbuf_add_alpha kwargs /* Old declaration accepted characters as 'r', 'g' and 'b' arguments. * However, that is flawed, as GTK+ in this case meant '8-bit * integers', not 'characters'. Override is needed to provide * backward compatibility for already existing uses. */ static PyObject * _wrap_gdk_pixbuf_add_alpha(PyGObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "substitute_color", "r", "g", "b", NULL }; int substitute_color, r, g, b; PyObject *py_ret; GdkPixbuf *ret; if (!PyArg_ParseTupleAndKeywords(args, kwargs,"iiii:gdk.Pixbuf.add_alpha", kwlist, &substitute_color, &r, &g, &b)) { /* Backward compatibility. */ PyObject *exc_type, *exc_value, *exc_traceback; PyErr_Fetch(&exc_type, &exc_value, &exc_traceback); if (!PyArg_ParseTupleAndKeywords(args, kwargs,"iccc:gdk.Pixbuf.add_alpha", kwlist, &substitute_color, &r, &g, &b)) { PyErr_Restore(exc_type, exc_value, exc_traceback); return NULL; } Py_XDECREF(exc_type); Py_XDECREF(exc_value); Py_XDECREF(exc_traceback); } ret = gdk_pixbuf_add_alpha(GDK_PIXBUF(self->obj), substitute_color, r, g, b); py_ret = pygobject_new((GObject *)ret); if (ret != NULL) g_object_unref(ret); return py_ret; }