Mercurial > pygame
diff src/pixelarray.c @ 860:41b22371307e
Changes from Marcus.
Added get_buffer() methods to Surface, and Sound.
Added a BufferProxy - which is a buffer interface only class.
Remember to change your Setup file - maybe just delete it if you have
made no changes to it as there is a new .c file.
| author | Rene Dudfield <renesd@gmail.com> |
|---|---|
| date | Sat, 01 Sep 2007 08:47:33 +0000 |
| parents | 4db78800a93a |
| children | 965348e5286c |
line wrap: on
line diff
--- a/src/pixelarray.c Sun Aug 26 07:50:24 2007 +0000 +++ b/src/pixelarray.c Sat Sep 01 08:47:33 2007 +0000 @@ -18,10 +18,22 @@ */ +#define PYGAMEAPI_PIXELARRAY_INTERNAL + #include "pygame.h" #include "pygamedocs.h" #include "surface.h" +#define GET_SLICE_VALS(array, start, end, ylen, ystep, xlen, xstep, padding,\ + _low, _high, _step, _pad) \ + start = array->start + _low; \ + end = array->end - array->xlen + _high; \ + ylen = array->ylen; \ + ystep = array->ystep; \ + xlen = _high - _low; \ + xstep = _step; \ + padding = _pad; + typedef struct { PyObject_HEAD @@ -70,10 +82,10 @@ static PyObject* _pxarray_item (PyPixelArray *array, Py_ssize_t _index); static PyObject* _pxarray_slice (PyPixelArray *array, Py_ssize_t low, Py_ssize_t high); -static int _array_assign_array (PyPixelArray *array, Py_ssize_t _index, - PyPixelArray *val); -static int _array_assign_sequence (PyPixelArray *array, Py_ssize_t _index, - PyObject *val); +static int _array_assign_array (PyPixelArray *array, Py_ssize_t low, + Py_ssize_t high, PyPixelArray *val); +static int _array_assign_sequence (PyPixelArray *array, Py_ssize_t low, + Py_ssize_t high, PyObject *val); static int _pxarray_ass_item (PyPixelArray *array, Py_ssize_t _index, PyObject *value); static int _pxarray_ass_slice (PyPixelArray *array, Py_ssize_t low, @@ -90,12 +102,9 @@ static int _pxarray_ass_subscript (PyPixelArray *array, PyObject* op, PyObject* value); */ -/* Buffer methods */ -static Py_ssize_t _pxarray_getreadbuf (PyPixelArray *array, Py_ssize_t _index, - const void **ptr); -static Py_ssize_t _pxarray_getwritebuf (PyPixelArray *array, Py_ssize_t _index, - const void **ptr); -static Py_ssize_t _pxarray_getsegcount (PyPixelArray *array, Py_ssize_t *lenp); + +/* C API interfaces */ +static PyObject* PyPixelArray_New (PyObject *surfobj); /** * Methods, which are bound to the PyPixelArray type. @@ -122,12 +131,12 @@ static PySequenceMethods _pxarray_sequence = { (lenfunc) _pxarray_length, /*sq_length*/ - NULL, /*(binaryfunc) _pxarray_concat,*/ /*sq_concat*/ + NULL, /*(binaryfunc) _pxarray_concat,*/ /*sq_concat*/ (ssizeargfunc) _pxarray_repeat, /*sq_repeat*/ (ssizeargfunc) _pxarray_item, /*sq_item*/ - NULL, /*(ssizessizeargfunc) _pxarray_slice,*/ /*sq_slice*/ + (ssizessizeargfunc) _pxarray_slice, /*sq_slice*/ (ssizeobjargproc) _pxarray_ass_item, /*sq_ass_item*/ - NULL, /*(ssizessizeobjargproc) _pxarray_ass_slice,*/ /*sq_ass_slice*/ + (ssizessizeobjargproc) _pxarray_ass_slice, /*sq_ass_slice*/ (objobjproc) _pxarray_contains, /*sq_contains*/ NULL, /*(binaryfunc) _pxarray_inplace_concat,*/ /*sq_inplace_concat*/ NULL, /*(ssizeargfunc) _pxarray_inplace_repeat*/ /*sq_inplace_repeat*/ @@ -143,17 +152,6 @@ /* (objobjargproc) _pxarray_ass_subscript, /\*mp_ass_subscript*\/ */ /* }; */ -/** - * Buffer interface support for the PyPixelArray. - */ -static PyBufferProcs _pxarray_as_buffer = -{ - (readbufferproc) _pxarray_getreadbuf, - (writebufferproc) _pxarray_getwritebuf, - (segcountproc) _pxarray_getsegcount, - NULL, -}; - static PyTypeObject PyPixelArray_Type = { PyObject_HEAD_INIT(NULL) @@ -173,9 +171,9 @@ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_getattro */ 0, /* tp_setattro */ - &_pxarray_as_buffer, /* tp_as_buffer */ + 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS, DOC_PYGAMEPIXELARRAY, /* tp_doc */ 0, /* tp_traverse */ @@ -334,21 +332,45 @@ switch (bpp) { case 1: + for (y = 0; y < array->ylen; y += array->ystep) + { + /* Construct the rows */ + PyString_ConcatAndDel (&string, PyString_FromString ("\n [")); + + for (x = 0; x < array->xlen - array->xstep; x += array->xstep) + { + /* Construct the columns */ + pixel = (Uint32)*((Uint8 *) pixels + array->start + x + + y * array->padding); + PyString_ConcatAndDel (&string, PyString_FromFormat + ("%d, ", pixel)); + } + pixel = (Uint32)*((Uint8 *) pixels + array->start + + x + y * array->padding); + PyString_ConcatAndDel (&string, PyString_FromFormat ("%d]", pixel)); + } break; case 2: + for (y = 0; y < array->ylen; y += array->ystep) + { + /* Construct the rows */ + PyString_ConcatAndDel (&string, PyString_FromString ("\n [")); + + for (x = 0; x < array->xlen - array->xstep; x += array->xstep) + { + /* Construct the columns */ + pixel = (Uint32)*((Uint16 *) pixels + array->start + x + + y * array->padding); + PyString_ConcatAndDel (&string, PyString_FromFormat + ("%d, ", pixel)); + } + pixel = (Uint32)*((Uint16 *) pixels + array->start + + x + y * array->padding); + PyString_ConcatAndDel (&string, PyString_FromFormat ("%d]", pixel)); + } break; case 3: - { - /* TODO: is this correct? */ - Uint8 *px; - px = ((Uint8 *) pixels + y * array->xstep); -#if SDL_BYTEORDER == SDL_LIL_ENDIAN - pixel = (px[0]) + (px[1] << 8) + (px[2] << 16); -#else - pixel = (px[2]) + (px[1] << 8) + (px[0] << 16); -#endif break; - } default: /* 4bpp */ for (y = 0; y < array->ylen; y += array->ystep) { @@ -363,7 +385,8 @@ PyString_ConcatAndDel (&string, PyString_FromFormat ("%d, ", pixel)); } - pixel = *((Uint32 *) pixels + array->start + x +y * array->padding); + pixel = *((Uint32 *) pixels + array->start + x + + y * array->padding); PyString_ConcatAndDel (&string, PyString_FromFormat ("%d]", pixel)); } break; @@ -459,8 +482,6 @@ static void _set_single_pixel (Uint8 *pixels, int bpp, Uint32 _index, Uint32 color) { - Uint32 pixel; - switch (bpp) { case 1: @@ -470,16 +491,7 @@ *((Uint16 *) pixels + _index) = (Uint16) color; break; case 3: - { - /* TODO: is this correct? */ - Uint8 *px = ((Uint8 *) pixels + _index); -#if SDL_BYTEORDER == SDL_LIL_ENDIAN - pixel = (px[0]) + (px[1] << 8) + (px[2] << 16); -#else - pixel = (px[2]) + (px[1] << 8) + (px[0] << 16); -#endif break; - } default: /* 4 bpp */ *((Uint32 *) pixels + _index) = color; break; @@ -500,17 +512,17 @@ Uint32 xstep; Uint32 ystep; Uint32 padding; + SDL_Surface *sf = PySurface_AsSurface (array->surface); - start = array->start + _start; - end = array->end - array->xlen + _start; + if (sf->format->BytesPerPixel == 3) + return RAISE (PyExc_TypeError, + "slicing for 24bpp surfaces not supported"); - ylen = array->ylen; - ystep = array->ystep; + if (_end == _start) + return RAISE (PyExc_IndexError, "array size must not be 0"); - xlen = _end - _start + 1; - xstep = _step; - - padding = array->xlen - xlen + 1; + GET_SLICE_VALS (array, start, end, ylen, ystep, xlen, xstep, padding, + _start, _end, _step, sf->w); return (PyObject *) _pxarray_new_internal (&PyPixelArray_Type, array->surface, start, end, xlen, ylen, @@ -571,7 +583,8 @@ return _get_single_pixel (pixels, bpp, array->start + _index * array->padding *array->ystep); - return _array_slice_internal (array, (Uint32) _index, (Uint32) _index, 1); + return _array_slice_internal + (array, (Uint32) _index, (Uint32) _index + 1, 1); } /** @@ -580,11 +593,22 @@ static PyObject* _pxarray_slice (PyPixelArray *array, Py_ssize_t low, Py_ssize_t high) { + if (low < 0) + low = 0; + else if (low > (Sint32) array->xlen) + low = array->xlen; + + if (high < low) + high = low; + else if (high > (Sint32) array->xlen) + high = array->xlen; + return _array_slice_internal (array, (Uint32) low, (Uint32) high, 1); } static int -_array_assign_array (PyPixelArray *array, Py_ssize_t _index, PyPixelArray *val) +_array_assign_array (PyPixelArray *array, Py_ssize_t low, Py_ssize_t high, + PyPixelArray *val) { SDL_Surface *surface; SDL_Surface *valsf; @@ -604,13 +628,9 @@ Uint32 padding; /* Set the correct slice indices */ - start = array->start + _index; - end = array->end - array->xlen + _index; - ylen = array->ylen; - ystep = array->ystep; - xlen = 1; - xstep = 1; - padding = array->xlen - xlen + 1; + surface = PySurface_AsSurface (array->surface); + GET_SLICE_VALS (array, start, end, ylen, ystep, xlen, xstep, padding, + low, high, 1, surface->w); if (val->ylen / val->ystep != ylen / ystep || val->xlen / val->xstep != xlen / xstep) @@ -620,7 +640,6 @@ return -1; } - surface = PySurface_AsSurface (array->surface); valsf = PySurface_AsSurface (val->surface); bpp = surface->format->BytesPerPixel; valbpp = valsf->format->BytesPerPixel; @@ -669,7 +688,8 @@ } static int -_array_assign_sequence (PyPixelArray *array, Py_ssize_t _index, PyObject *val) +_array_assign_sequence (PyPixelArray *array, Py_ssize_t low, Py_ssize_t high, + PyObject *val) { SDL_Surface *surface; Uint32 x = 0; @@ -694,13 +714,8 @@ pixels = (Uint8 *) surface->pixels; /* Set the correct slice indices */ - start = array->start + _index; - end = array->end - array->xlen + _index; - ylen = array->ylen; - ystep = array->ystep; - xlen = 1; - xstep = 1; - padding = array->xlen - xlen + 1; + GET_SLICE_VALS (array, start, end, ylen, ystep, xlen, xstep, padding, + low, high, 1, surface->w); if ((Uint32)seqsize != ylen / ystep) { @@ -807,12 +822,13 @@ if (PyPixelArray_Check (value)) { PyErr_Clear (); /* _get_color_from_object */ - return _array_assign_array (array, _index, (PyPixelArray *) value); + return _array_assign_array (array, _index, _index + 1, + (PyPixelArray *) value); } else if (PySequence_Check (value)) { PyErr_Clear (); /* _get_color_from_object */ - return _array_assign_sequence (array, _index, value); + return _array_assign_sequence (array, _index, _index + 1, value); } else /* Error already set by _get_color_from_object(). */ return -1; @@ -827,13 +843,8 @@ } /* Set the correct slice indices */ - start = array->start + _index; - end = array->end - array->xlen + _index; - ylen = array->ylen; - ystep = array->ystep; - xlen = 1; - xstep = 1; - padding = array->xlen - xlen + 1; + GET_SLICE_VALS (array, start, end, ylen, ystep, xlen, xstep, padding, + _index, _index + 1, 1, surface->w); /* Single value assignment. */ for (y = 0; y < ylen; y += ystep) @@ -873,8 +884,30 @@ _pxarray_ass_slice (PyPixelArray *array, Py_ssize_t low, Py_ssize_t high, PyObject *value) { - /* TODO */ - PyErr_SetString (PyExc_NotImplementedError, "method not implemented"); + SDL_Surface *surface; + Uint32 x; + Uint32 y; + int bpp; + Uint8 *pixels; + Uint32 color = 0; + Py_ssize_t offset = 0; + + Uint32 start; + Uint32 end; + Uint32 xlen; + Uint32 ylen; + Uint32 xstep; + Uint32 ystep; + Uint32 padding; + + surface = PySurface_AsSurface (array->surface); + bpp = surface->format->BytesPerPixel; + pixels = (Uint8 *) surface->pixels; + + GET_SLICE_VALS (array, start, end, ylen, ystep, xlen, xstep, padding, + low, high, 1, surface->w); + + PyErr_SetString (PyExc_NotImplementedError, "method not implementeda"); return -1; } @@ -1126,143 +1159,52 @@ /* return -1; */ /* } */ -/**** Buffer interfaces ****/ - -static Py_ssize_t -_pxarray_getreadbuf (PyPixelArray *array, Py_ssize_t _index, const void **ptr) +/**** C API interfaces ****/ +static PyObject* PyPixelArray_New (PyObject *surfobj) { SDL_Surface *surface; - size_t mod = 0; - if (_index != 0) - { - PyErr_SetString (PyExc_SystemError, - "Accessing non-existent array segment"); - return -1; - } - if (array->parent) - { - *ptr = NULL; - return 0; /* TODO: subarrays? */ - } - surface = PySurface_AsSurface (array->surface); - - switch (surface->format->BytesPerPixel) - { - case 1: - mod = sizeof (Uint8); - break; - case 2: - mod = sizeof (Uint16); - break; - case 3: - mod = sizeof (Uint8) * 3; - break; - default: - mod = sizeof (Uint32); - break; - } - - *ptr = (void *) surface->pixels; - return surface->w * surface->h * mod; -} - -static Py_ssize_t -_pxarray_getwritebuf (PyPixelArray *array, Py_ssize_t _index, const void **ptr) -{ - SDL_Surface *surface = NULL; - size_t mod = 0; - - if (_index != 0) - { - PyErr_SetString (PyExc_SystemError, - "Accessing non-existent array segment"); - return -1; - } - if (array->parent) - { - *ptr = NULL; - return 0; /* TODO: subarrays? */ - } + if (!PySurface_Check (surfobj)) + return RAISE (PyExc_TypeError, "argument is no a Surface"); - switch (surface->format->BytesPerPixel) - { - case 1: - mod = sizeof (Uint8); - break; - case 2: - mod = sizeof (Uint16); - break; - case 3: - mod = sizeof (Uint8) * 3; - break; - default: - mod = sizeof (Uint32); - break; - } - - surface = PySurface_AsSurface (array->surface); - *ptr = (void *) surface->pixels; - return surface->w * surface->h * mod; -} + surface = PySurface_AsSurface (surfobj); + if (surface->format->BytesPerPixel < 1 || + surface->format->BytesPerPixel > 4) + return RAISE (PyExc_ValueError, + "unsupport bit depth for reference array"); -static Py_ssize_t -_pxarray_getsegcount (PyPixelArray *array, Py_ssize_t *lenp) -{ - if (array->parent) - { - *lenp = 0; - return 0; /* TODO: subarrays? */ - } - if (lenp) - { - SDL_Surface *surface = PySurface_AsSurface (array->surface); - size_t mod = 0; - - switch (surface->format->BytesPerPixel) - { - case 1: - mod = sizeof (Uint8); - break; - case 2: - mod = sizeof (Uint16); - break; - case 3: - mod = sizeof (Uint8) * 3; - break; - default: - mod = sizeof (Uint32); - break; - } - - *lenp = surface->w * surface->h * mod; - if (array->parent) - { - *lenp = 0; - return 1; /* TODO: subarrays? */ - } - } - return 1; + return (PyObject *) _pxarray_new_internal + (&PyPixelArray_Type, surfobj, 0, (Uint32) surface->w * surface->h, + (Uint32) surface->w, (Uint32) surface->h, 1, 1, (Uint32) surface->w, + NULL); } -static PyMethodDef surfarray_builtins[] = -{ - { NULL, NULL, 0, NULL } -}; - PYGAME_EXPORT void initpixelarray (void) { PyObject *module; + PyObject *dict; + PyObject *apiobj; + static void* c_api[PYGAMEAPI_PIXELARRAY_NUMSLOTS]; if (PyType_Ready (&PyPixelArray_Type) < 0) return; /* create the module */ module = Py_InitModule3 ("pixelarray", NULL, NULL); + PyPixelArray_Type.tp_getattro = PyObject_GenericGetAttr; Py_INCREF (&PyPixelArray_Type); PyModule_AddObject (module, "PixelArray", (PyObject *) &PyPixelArray_Type); - + + dict = PyModule_GetDict (module); + + c_api[0] = &PyPixelArray_Type; + c_api[1] = PyPixelArray_New; + apiobj = PyCObject_FromVoidPtr (c_api, NULL); + PyDict_SetItemString (dict, PYGAMEAPI_LOCAL_ENTRY, apiobj); + Py_DECREF (apiobj); + + /*imported needed apis*/ import_pygame_base (); import_pygame_surface ();
