diff options
author | James Henstridge <james@daa.com.au> | 1999-08-08 14:51:50 +0000 |
---|---|---|
committer | James Henstridge <jamesh@src.gnome.org> | 1999-08-08 14:51:50 +0000 |
commit | e36ac1a21a255fc4655834e1d0272fdad4a89f51 (patch) | |
tree | 1929d375ab325a162385804f0dd3fde839c5c27d | |
parent | 14d3f7b03cb3df32ba92e9b8f24475a421888c47 (diff) | |
download | pygtk-e36ac1a21a255fc4655834e1d0272fdad4a89f51.tar.gz |
updated news file.
1999-08-08 James Henstridge <james@daa.com.au>
* NEWS: updated news file.
* configure.in: increased version number to 0.6.2.
* gdkimlibmodule.c (_wrap_gdk_imlib_image_get_array): make sure that
the image data is not freed while the returned array is in use, so
that we don't get into an inconsistent state.
* gtk.py: added gdkrgb functions to this file.
* gtkmodule.c: added the gdkrgb functions for drawing rgb and greyscale
images.
(gdk_draw_array): a new function that will draw a numpy array to a
drawable with gdkrgb. It is written so that it can handle slicing
on the first two axes -- it does not handle non contiguous data on
the third axis.
-rw-r--r-- | ChangeLog | 19 | ||||
-rw-r--r-- | NEWS | 18 | ||||
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | gdkimlibmodule.c | 11 | ||||
-rw-r--r-- | gtk.py | 52 | ||||
-rw-r--r-- | gtkmodule.c | 164 |
6 files changed, 259 insertions, 7 deletions
@@ -1,3 +1,22 @@ +1999-08-08 James Henstridge <james@daa.com.au> + + * NEWS: updated news file. + + * configure.in: increased version number to 0.6.2. + + * gdkimlibmodule.c (_wrap_gdk_imlib_image_get_array): make sure that + the image data is not freed while the returned array is in use, so + that we don't get into an inconsistent state. + + * gtk.py: added gdkrgb functions to this file. + + * gtkmodule.c: added the gdkrgb functions for drawing rgb and greyscale + images. + (gdk_draw_array): a new function that will draw a numpy array to a + drawable with gdkrgb. It is written so that it can handle slicing + on the first two axes -- it does not handle non contiguous data on + the third axis. + 1999-08-04 Matt Wilson <msw@redhat.com> * GdkImlib.py (create_image_from_xpm): new wrapper for creating @@ -1,3 +1,21 @@ +pygtk-0.6.2: + - Alright, threading should work correctly with multiple threads + accessing GTK (assuming they use threads_enter/leave). Thanks go + to Matt Wilson and Paul Fisher for this code. + - A pygtk.h header file is now installed that should make it easier + to write extensions to pygtk. + - There is now optional support for the gtkglarea widget and the + libglade library now. + - There is support for gdkrgb functions for rendering rgb and greyscale + image data to a drawable. + - Optional support for numpy arrays. You can create a GdkImlibImage + from a numpy array, and manipulate an image's data as an array. + Also there is a gdk_draw_array wrapper that uses gdkrgb to render + an array to a drawable. The code for the imlib stuff is based on + stuff submitted by Travis Oliphant. + - The GdkWindow type now has some methods for manipulating properties, + and has an xid attribute for getting the X window ID of the window. + pygtk-0.6.1: 22-May-1999 - Fixed a few bugs to do with the threading patches I applied in the last release. Threading should now work correctly. diff --git a/configure.in b/configure.in index 47818b00..c1288396 100644 --- a/configure.in +++ b/configure.in @@ -2,7 +2,7 @@ AC_INIT dnl for gnome-python: -AM_INIT_AUTOMAKE(pygtk, 0.6.1) +AM_INIT_AUTOMAKE(pygtk, 0.6.2) AM_PATH_PYTHON AM_INIT_PYEXEC_MOD diff --git a/gdkimlibmodule.c b/gdkimlibmodule.c index 7a341078..3a8f73da 100644 --- a/gdkimlibmodule.c +++ b/gdkimlibmodule.c @@ -797,12 +797,11 @@ static PyObject *_wrap_gdk_imlib_image_get_array(PyObject *self, PyObject *args) (char *)obj->rgb_data); if (ap_data == NULL) return NULL; - /* this is necessary if you want to manipulate the rgb data after - * destroying the image. It causes a reference imbalance, and - * I don't see when you would want to do this (you can always copy - * the array). - */ - /* Py_INCREF(image); */ + /* this makes sure the GdkImlibImage is not freed while someone has a + * reference to the new array. */ + Py_INCREF(image); + ap_data->base = image; + return PyArray_Return(ap_data); } #endif @@ -1977,6 +1977,29 @@ class GtkDrawingArea(GtkWidget): def draw_lines(self, gc, points): if not self.__win: self.__cache_win() _gtk.gdk_draw_lines(self.__win, gc, points) + # these are the gdkrgb functions + def draw_rgb_image(self, gc, x, y, width, height, + dither, buffer, rowstride): + if not self.__win: self.__cache_win() + _gtk.gdk_draw_rgb_image(self.__win, gc, x, y, width, height, + dither, buffer, rowstride) + def draw_rgb_32_image(self, gc, x, y, width, height, + dither, buffer, rowstride): + if not self.__win: self.__cache_win() + _gtk.gdk_draw_rgb_32_image(self.__win, gc, x, y, width, height, + dither, buffer, rowstride) + def draw_gray_image(self, gc, x, y, width, height, + dither, buffer, rowstride): + if not self.__win: self.__cache_win() + _gtk.gdk_draw_gray_image(self.__win, gc, x, y, width, height, + dither, buffer, rowstride) + + # see the comment for draw_array closer to the bottom of this file. + if hasattr(_gtk, "gdk_draw_array"): + def draw_array(self, gc, x, y, dither, array): + if not self.__win: self.__cache_win() + _gtk.gdk_draw_array(self.__win, gc, x, y, dither,array) + class GtkCurve(GtkDrawingArea): get_type = _gtk.gtk_curve_get_type @@ -2642,6 +2665,29 @@ def draw_segments(drawable, gc, segs): def draw_lines(drawable, gc, points): _gtk.gdk_draw_lines(drawable, gc, points) +# these are the gdkrgb functions +def draw_rgb_image(drawable, gc, x, y, width, height, + dither, buffer, rowstride): + _gtk.gdk_draw_rgb_image(drawable, gc, x, y, width, height, + dither, buffer, rowstride) +def draw_rgb_32_image(drawable, gc, x, y, width, height, + dither, buffer, rowstride): + _gtk.gdk_draw_rgb_32_image(drawable, gc, x, y, width, height, + dither, buffer, rowstride) +def draw_gray_image(drawable, gc, x, y, width, height, + dither, buffer, rowstride): + _gtk.gdk_draw_gray_image(drawable, gc, x, y, width, height, + dither, buffer, rowstride) + +# this function renders an unsigned byte (type code 'b') numpy array to a +# drawable. If it is a MxN or MxNx1 array, it is assumed to be a grey image. +# If it is a MxNx3 or MxNx4 array, it is assumed to be an rgb image. +# It should accept images that have been sliced along their first two axes, +# if you want to only draw part of the image. +if hasattr(_gtk, "gdk_draw_array"): + def draw_array(drawable, gc, x, y, dither, array): + _gtk.gdk_draw_array(drawable, gc, x, y, dither, array) + # screen size def screen_width(): @@ -2663,6 +2709,12 @@ def threads_leave(): def gdk_flush(): _gtk.gdk_flush() +# these actually push/pop a visual/colormap pair. +def push_rgb_visual(): + _gtk.gtk_rgb_push_visual() +def pop_visual(): + _gtk.gtk_pop_visual() + # these are prefixed with underscores, since they are low level, and # would break if pygtk was ported to windows. def _window_foreign_new(xid): diff --git a/gtkmodule.c b/gtkmodule.c index adaaba5b..cd310c33 100644 --- a/gtkmodule.c +++ b/gtkmodule.c @@ -20,6 +20,10 @@ #include <Python.h> #include <sysmodule.h> +#ifdef HAVE_NUMPY +#include <arrayobject.h> +#endif + #include <gtk/gtk.h> #define WITH_XSTUFF @@ -5821,6 +5825,154 @@ static PyObject *_wrap_gdk_threads_leave(PyObject *self, PyObject *args) { return Py_None; } +/* gdkrgb stuff -- will be needed when gdk_pixbuf stuff is added */ + +static PyObject *_wrap_gtk_rgb_push_visual(PyObject *self, PyObject *args) { + if (!PyArg_ParseTuple(args, ":gtk_rgb_push_visual")) + return NULL; + gtk_widget_push_colormap(gdk_rgb_get_cmap()); + gtk_widget_push_visual(gdk_rgb_get_visual()); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject *_wrap_gtk_pop_visual(PyObject *self, PyObject *args) { + if (!PyArg_ParseTuple(args, ":gtk_pop_visual")) + return NULL; + gtk_widget_pop_colormap(); + gtk_widget_pop_visual(); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject *_wrap_gdk_draw_rgb_image(PyObject *self, PyObject *args) { + PyObject *drawable, *gc, *py_dith; + gint x, y, width, height, rowstride = -1, len; + GdkRgbDither dith; + guchar *rgb_buf; + + if (!PyArg_ParseTuple(args, "O!O!iiiiOs#|i:gdk_draw_rgb_image", + &PyGdkWindow_Type, &drawable, &PyGdkGC_Type, &gc, + &x, &y, &width, &height, &py_dith, &rgb_buf, &len, + &rowstride)) + return NULL; + if (PyGtkEnum_get_value(GTK_TYPE_GDK_RGB_DITHER, py_dith, (gint *)&dith)) + return NULL; + if (rowstride == -1) + rowstride = width * 3; + gdk_draw_rgb_image(PyGdkWindow_Get(drawable), PyGdkGC_Get(gc), x, y, + width, height, dith, rgb_buf, rowstride); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject *_wrap_gdk_draw_rgb_32_image(PyObject *self, PyObject *args) { + PyObject *drawable, *gc, *py_dith; + gint x, y, width, height, rowstride = -1, len; + GdkRgbDither dith; + guchar *rgb_buf; + + if (!PyArg_ParseTuple(args, "O!O!iiiiOs#|i:gdk_draw_rgb_32_image", + &PyGdkWindow_Type, &drawable, &PyGdkGC_Type, &gc, + &x, &y, &width, &height, &py_dith, &rgb_buf, &len, + &rowstride)) + return NULL; + if (PyGtkEnum_get_value(GTK_TYPE_GDK_RGB_DITHER, py_dith, (gint *)&dith)) + return NULL; + if (rowstride == -1) + rowstride = width * 4; + gdk_draw_rgb_32_image(PyGdkWindow_Get(drawable), PyGdkGC_Get(gc), x, y, + width, height, dith, rgb_buf, rowstride); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject *_wrap_gdk_draw_gray_image(PyObject *self, PyObject *args) { + PyObject *drawable, *gc, *py_dith; + gint x, y, width, height, rowstride = -1, len; + GdkRgbDither dith; + guchar *buf; + + if (!PyArg_ParseTuple(args, "O!O!iiiiOs#|i:gdk_draw_gray_image", + &PyGdkWindow_Type, &drawable, &PyGdkGC_Type, &gc, + &x, &y, &width, &height, &py_dith, &buf, &len, + &rowstride)) + return NULL; + if (PyGtkEnum_get_value(GTK_TYPE_GDK_RGB_DITHER, py_dith, (gint *)&dith)) + return NULL; + if (rowstride == -1) + rowstride = width; + gdk_draw_gray_image(PyGdkWindow_Get(drawable), PyGdkGC_Get(gc), x, y, + width, height, dith, buf, rowstride); + Py_INCREF(Py_None); + return Py_None; +} + +#ifdef HAVE_NUMPY +/* this function renders an array to a drawable. If it is a MxN or MxNx1 + * array, it is considered to be a grey image. If it is an MxNx3 or MxNx4 + * array, it is considered to be an rgb image. The second two axes of the + * array must be contiguous (ie. array->strides[1] == 1,3 or 4, + * array->strides[2] == 1). The array->strides[0] is used to deduce the + * rowstride value for the data. This allows you to draw a slice of the image + * data. */ +static PyObject *_wrap_gdk_draw_array(PyObject *self, PyObject *args) { + PyObject *drawable, *gc, *py_dith; + PyArrayObject *array; + gint x, y, width, height, rowstride = -1, len; + GdkRgbDither dith; + guchar *buf; + + if (!PyArg_ParseTuple(args, "O!O!iiOO!:gdk_draw_array", + &PyGdkWindow_Type, &drawable, &PyGdkGC_Type, &gc, + &x, &y, &py_dith, &PyArray_Type, &array)) + return NULL; + if (PyGtkEnum_get_value(GTK_TYPE_GDK_RGB_DITHER, py_dith, (gint *)&dith)) + return NULL; + if (array->descr->type_num != PyArray_UBYTE) { + PyErr_SetString(PyExc_TypeError, "array data must be unsigned bytes"); + return NULL; + } + if (array->nd < 2) { + PyErr_SetString(PyExc_TypeError, "array must have at least 2 axes"); + return NULL; + } + width = array->dimensions[1]; + height = array->dimensions[0]; + buf = (guchar *)array->data; + rowstride = array->strides[0]; + if (array->nd == 2 || array->nd == 3 && array->dimensions[2] == 1) { + /* grey image */ + if (array->strides[1] != 1) { + PyErr_SetString(PyExc_TypeError, "second axis must be contiguous"); + return NULL; + } + gdk_draw_gray_image(PyGdkWindow_Get(drawable), PyGdkGC_Get(gc), x, y, + width, height, dith, buf, rowstride); + } else if (array->nd == 3 && array->dimensions[2] == 3) { + if (array->strides[1] != 3) { + PyErr_SetString(PyExc_TypeError, "second axis must be contiguous"); + return NULL; + } + gdk_draw_rgb_image(PyGdkWindow_Get(drawable), PyGdkGC_Get(gc), x, y, + width, height, dith, buf, rowstride); + } else if (array->nd == 3 && array->dimensions[2] == 4) { + if (array->strides[1] != 4) { + PyErr_SetString(PyExc_TypeError, "second axis must be contiguous"); + return NULL; + } + gdk_draw_rgb_32_image(PyGdkWindow_Get(drawable), PyGdkGC_Get(gc), x, y, + width, height, dith, buf, rowstride); + } else { + PyErr_SetString(PyExc_TypeError, + "array must be MxN or MxNxP where P is 1, 3 or 4"); + return NULL; + } + Py_INCREF(Py_None); + return Py_None; +} +#endif + static PyMethodDef _gtkmoduleMethods[] = { { "gtk_signal_connect", _wrap_gtk_signal_connect, 1 }, { "gtk_signal_connect_after", _wrap_gtk_signal_connect_after, 1 }, @@ -5950,6 +6102,14 @@ static PyMethodDef _gtkmoduleMethods[] = { { "gdk_window_foreign_new", _wrap_gdk_window_foreign_new, 1 }, { "gdk_get_root_win", _wrap_gdk_get_root_win, 1 }, #endif + { "gtk_rgb_push_visual", _wrap_gtk_rgb_push_visual, 1 }, + { "gtk_pop_visual", _wrap_gtk_pop_visual, 1 }, + { "gdk_draw_rgb_image", _wrap_gdk_draw_rgb_image, 1 }, + { "gdk_draw_rgb_32_image", _wrap_gdk_draw_rgb_32_image, 1 }, + { "gdk_draw_gray_image", _wrap_gdk_draw_gray_image, 1 }, +#ifdef HAVE_NUMPY + { "gdk_draw_array", _wrap_gdk_draw_array, 1 }, +#endif { NULL, NULL } }; @@ -5995,6 +6155,10 @@ void init_gtk() { m = Py_InitModule("_gtk", _gtkmoduleMethods); d = PyModule_GetDict(m); +#ifdef HAVE_NUMPY + import_array(); +#endif + /* initialise the boxed_funcs hash_table */ boxed_funcs = g_hash_table_new(g_direct_hash, g_direct_equal); |