Mercurial > pygame
view src/pixelarray.c @ 852:4db78800a93a
A PixelArray class, which is meant to replace surfarray.
It acts as a buffer for surface data.
Written by Marcus.
It's not quite complete, but basic functionality is implemented.
| author | Rene Dudfield <renesd@gmail.com> |
|---|---|
| date | Wed, 22 Aug 2007 08:10:12 +0000 |
| parents | |
| children | 41b22371307e |
line wrap: on
line source
/* pygame - Python Game Library Copyright (C) 2007 Marcus von Appen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "pygame.h" #include "pygamedocs.h" #include "surface.h" typedef struct { PyObject_HEAD PyObject *dict; /* dict for subclassing */ PyObject *weakrefs; /* Weakrefs for subclassing */ PyObject *surface; /* Surface associated with the array. */ PyObject *lock; /* Lock object for the surface. */ Uint32 start; /* Start offset for subarrays */ Uint32 end; /* End offset for subarrays */ Uint32 xlen; /* X segment length. */ Uint32 ylen; /* Y segment length. */ Uint32 xstep; /* X offset step width. */ Uint32 ystep; /* Y offset step width. */ Uint32 padding; /* Padding to get to the next x offset. */ PyObject *parent; /* Parent pixel array */ } PyPixelArray; static PyPixelArray* _pxarray_new_internal (PyTypeObject *type, PyObject *surface, Uint32 start, Uint32 end, Uint32 xlen, Uint32 ylen, Uint32 xstep, Uint32 ystep, Uint32 padding, PyObject *parent); static PyObject* _pxarray_new (PyTypeObject *type, PyObject *args, PyObject *kwds); static void _pxarray_dealloc (PyPixelArray *self); static PyObject* _pxarray_get_dict (PyPixelArray *self, void *closure); static PyObject* _pxarray_get_surface (PyPixelArray *self, void *closure); static PyObject* _pxarray_repr (PyPixelArray *array); static int _get_color_from_object (PyObject *val, SDL_PixelFormat *format, Uint32 *color); static PyObject* _get_single_pixel (Uint8 *pixels, int bpp, Uint32 _index); static void _set_single_pixel (Uint8 *pixels, int bpp, Uint32 _index, Uint32 color); static PyObject* _array_slice_internal (PyPixelArray *array, Uint32 _start, Uint32 _end, Uint32 _step); /* Sequence methods */ static Py_ssize_t _pxarray_length (PyPixelArray *array); static PyObject* _pxarray_concat (PyPixelArray *array, PyObject *value); static PyObject* _pxarray_repeat (PyPixelArray *a, Py_ssize_t n); 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 _pxarray_ass_item (PyPixelArray *array, Py_ssize_t _index, PyObject *value); static int _pxarray_ass_slice (PyPixelArray *array, Py_ssize_t low, Py_ssize_t high, PyObject *value); static int _pxarray_contains (PyPixelArray *array, PyObject *value); static PyObject* _pxarray_inplace_concat (PyPixelArray *array, PyObject *seq); static PyObject* _pxarray_inplace_repeat (PyPixelArray *array, Py_ssize_t n); /* Mapping methods */ /* static int _get_subslice (SDL_Surface *surface, PyObject *op, Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step); static PyObject* _pxarray_subscript (PyPixelArray *array, PyObject *op); 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); /** * Methods, which are bound to the PyPixelArray type. */ static PyMethodDef _pxarray_methods[] = { { NULL, NULL, 0, NULL } }; /** * Getters and setters for the PyPixelArray. */ static PyGetSetDef _pxarray_getsets[] = { { "__dict__", (getter) _pxarray_get_dict, NULL, NULL, NULL }, { "surface", (getter) _pxarray_get_surface, NULL, NULL, DOC_PIXELARRAYSURFACE }, { NULL, NULL, NULL, NULL, NULL } }; /** * Sequence interface support for the PyPixelArray. */ static PySequenceMethods _pxarray_sequence = { (lenfunc) _pxarray_length, /*sq_length*/ NULL, /*(binaryfunc) _pxarray_concat,*/ /*sq_concat*/ (ssizeargfunc) _pxarray_repeat, /*sq_repeat*/ (ssizeargfunc) _pxarray_item, /*sq_item*/ NULL, /*(ssizessizeargfunc) _pxarray_slice,*/ /*sq_slice*/ (ssizeobjargproc) _pxarray_ass_item, /*sq_ass_item*/ NULL, /*(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*/ }; /** * Mapping interface support for the PyPixelArray. */ /* static PyMappingMethods _pxarray_mapping = */ /* { */ /* (inquiry) _pxarray_length, /\*mp_length*\/ */ /* (binaryfunc) _pxarray_subscript, /\*mp_subscript*\/ */ /* (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) 0, "PixelArray", /* tp_name */ sizeof (PyPixelArray), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor) _pxarray_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ (reprfunc) &_pxarray_repr, /* tp_repr */ 0, /* tp_as_number */ &_pxarray_sequence, /* tp_as_sequence */ 0, /*&_pxarray_mapping ,*/ /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ &_pxarray_as_buffer, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS, DOC_PYGAMEPIXELARRAY, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ offsetof (PyPixelArray, weakrefs), /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ _pxarray_methods, /* tp_methods */ 0, /* tp_members */ _pxarray_getsets, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ offsetof (PyPixelArray, dict), /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ _pxarray_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ 0, /* tp_mro */ 0, /* tp_cache */ 0, /* tp_subclasses */ 0, /* tp_weaklist */ 0 /* tp_del */ }; #define PyPixelArray_Check(o) \ ((o)->ob_type == (PyTypeObject *) &PyPixelArray_Type) static PyPixelArray* _pxarray_new_internal (PyTypeObject *type, PyObject *surface, Uint32 start, Uint32 end, Uint32 xlen, Uint32 ylen, Uint32 xstep, Uint32 ystep, Uint32 padding, PyObject *parent) { PyPixelArray *self = (PyPixelArray *) type->tp_alloc (type, 0); if (!self) return NULL; self->surface = (PyObject *) surface; if (surface) { self->lock = PySurface_LockLifetime (surface); if (!self->lock) { self->ob_type->tp_free ((PyObject *) self); return NULL; } } self->weakrefs = NULL; self->dict = NULL; self->start = start; self->end = end; self->xlen = xlen; self->ylen = ylen; self->xstep = xstep; self->ystep = ystep; self->padding = padding; self->parent = parent; return self; } /** * Creates a new PyPixelArray. */ static PyObject* _pxarray_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *surfobj; SDL_Surface* surface; if (!PyArg_ParseTuple (args, "O!", &PySurface_Type, &surfobj)) return NULL; surface = PySurface_AsSurface (surfobj); if (surface->format->BytesPerPixel < 1 || surface->format->BytesPerPixel > 4) return RAISE (PyExc_ValueError, "unsupport bit depth for reference array"); return (PyObject *) _pxarray_new_internal (type, surfobj, 0, (Uint32) surface->w * surface->h, (Uint32) surface->w, (Uint32) surface->h, 1, 1, (Uint32) surface->w, NULL); } /** * Deallocates the PyPixelArray and its members. */ static void _pxarray_dealloc (PyPixelArray *self) { if (self->weakrefs) PyObject_ClearWeakRefs ((PyObject *) self); if (self->lock) { Py_DECREF (self->lock); } Py_XDECREF (self->dict); self->ob_type->tp_free ((PyObject *) self); } /**** Getter and setter access ****/ /** * Getter for PixelArray.__dict__. */ static PyObject* _pxarray_get_dict (PyPixelArray *self, void *closure) { if (!self->dict) { self->dict = PyDict_New (); if (!self->dict) return NULL; } Py_INCREF (self->dict); return self->dict; } /** * Getter for PixelArray.surface */ static PyObject* _pxarray_get_surface (PyPixelArray *self, void *closure) { Py_XINCREF (self->surface); return self->surface; } /**** Methods ****/ /** * repr(PixelArray) */ static PyObject* _pxarray_repr (PyPixelArray *array) { PyObject *string; SDL_Surface *surface; int bpp; Uint8 *pixels; Uint32 pixel; Uint32 x = 0; Uint32 y = 0; surface = PySurface_AsSurface (array->surface); bpp = surface->format->BytesPerPixel; pixels = (Uint8 *) surface->pixels; string = PyString_FromString ("PixelArray("); switch (bpp) { case 1: break; case 2: 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) { /* 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 *) pixels + array->start + x + y * array->padding); PyString_ConcatAndDel (&string, PyString_FromFormat ("%d, ", pixel)); } pixel = *((Uint32 *) pixels + array->start + x +y * array->padding); PyString_ConcatAndDel (&string, PyString_FromFormat ("%d]", pixel)); } break; } PyString_ConcatAndDel (&string, PyString_FromString ("\n)")); return string; } /** * Tries to retrieve a valid color for a Surface. */ static int _get_color_from_object (PyObject *val, SDL_PixelFormat *format, Uint32 *color) { Uint8 rgba[4]; if (PyInt_Check (val)) { int intval = PyInt_AsLong (val); if (intval < 0) { if (!PyErr_Occurred ()) PyErr_SetString (PyExc_ValueError, "invalid color argument"); return 0; } *color = (Uint32) intval; return 1; } else if (PyLong_Check (val)) { long long longval = -1; /* Plain index: array[x, */ longval = PyLong_AsLong (val); if ((longval < INT_MIN) || (longval > INT_MAX)) { PyErr_SetString(PyExc_ValueError, "index too big for array access"); return 0; } *color = (Uint32) longval; return 1; } else if (RGBAFromObj (val, rgba)) { *color = (Uint32) SDL_MapRGBA (format, rgba[0], rgba[1], rgba[2], rgba[3]); return 1; } else PyErr_SetString (PyExc_ValueError, "invalid color argument"); return 0; } /** * Retrieves a single pixel located at index from the surface pixel * array. */ static PyObject* _get_single_pixel (Uint8 *pixels, int bpp, Uint32 _index) { Uint32 pixel; switch (bpp) { case 1: pixel = (Uint32)*((Uint8 *) pixels + _index); break; case 2: pixel = (Uint32)*((Uint16 *) pixels + _index); 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 */ pixel = *((Uint32 *) pixels + _index); break; } return PyInt_FromLong ((long)pixel); } /** * Sets a single pixel located at index from the surface pixel array. */ static void _set_single_pixel (Uint8 *pixels, int bpp, Uint32 _index, Uint32 color) { Uint32 pixel; switch (bpp) { case 1: *((Uint8 *) pixels + _index) = (Uint8) color; break; case 2: *((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; } } /** * Creates a 2D slice of the array. */ static PyObject* _array_slice_internal (PyPixelArray *array, Uint32 _start, Uint32 _end, Uint32 _step) { Uint32 start; Uint32 end; Uint32 xlen; Uint32 ylen; Uint32 xstep; Uint32 ystep; Uint32 padding; start = array->start + _start; end = array->end - array->xlen + _start; ylen = array->ylen; ystep = array->ystep; xlen = _end - _start + 1; xstep = _step; padding = array->xlen - xlen + 1; return (PyObject *) _pxarray_new_internal (&PyPixelArray_Type, array->surface, start, end, xlen, ylen, xstep, ystep, padding, (PyObject *) array); } /**** Sequence interfaces ****/ /** * len (array) */ static Py_ssize_t _pxarray_length (PyPixelArray *array) { if (array->xlen > 1) return array->xlen / array->xstep; return array->ylen / array->ystep; } /** * TODO */ static PyObject* _pxarray_concat (PyPixelArray *array, PyObject *value) { /* TODO */ return RAISE (PyExc_NotImplementedError, "method not implemented"); } /** * array * 2 */ static PyObject* _pxarray_repeat (PyPixelArray *array, Py_ssize_t n) { /* TODO */ return RAISE (PyExc_NotImplementedError, "method not implemented"); } /** * array[x] */ static PyObject* _pxarray_item (PyPixelArray *array, Py_ssize_t _index) { SDL_Surface *surface; int bpp; Uint8 *pixels; surface = PySurface_AsSurface (array->surface); bpp = surface->format->BytesPerPixel; pixels = (Uint8 *) surface->pixels; if (_index < 0) return RAISE (PyExc_IndexError, "array index out of range"); if (array->xlen == 1) /* Access of a single column. */ return _get_single_pixel (pixels, bpp, array->start + _index * array->padding *array->ystep); return _array_slice_internal (array, (Uint32) _index, (Uint32) _index, 1); } /** * array[x:y] */ static PyObject* _pxarray_slice (PyPixelArray *array, Py_ssize_t low, Py_ssize_t high) { return _array_slice_internal (array, (Uint32) low, (Uint32) high, 1); } static int _array_assign_array (PyPixelArray *array, Py_ssize_t _index, PyPixelArray *val) { SDL_Surface *surface; SDL_Surface *valsf; Uint32 x; Uint32 y; int bpp; int valbpp; Uint8 *pixels; Py_ssize_t offset = 0; Uint32 start; Uint32 end; Uint32 xlen; Uint32 ylen; Uint32 xstep; Uint32 ystep; 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; if (val->ylen / val->ystep != ylen / ystep || val->xlen / val->xstep != xlen / xstep) { /* Bounds do not match. */ PyErr_SetString (PyExc_ValueError, "array sizes do not match"); return -1; } surface = PySurface_AsSurface (array->surface); valsf = PySurface_AsSurface (val->surface); bpp = surface->format->BytesPerPixel; valbpp = valsf->format->BytesPerPixel; pixels = (Uint8 *) surface->pixels; if (bpp != valbpp) { /* bpp do not match. */ /* TODO */ PyErr_SetString (PyExc_ValueError, "bit depths do not match"); return -1; } /* Single value assignment. */ for (y = 0; y < ylen; y += ystep) { for (x = 0; x < xlen; x += xstep) { offset = start + x + y * padding; switch (bpp) { case 1: *((Uint8 *) pixels + offset) = (Uint8)*((Uint8 *) valsf->pixels + val->start + x * val->xstep + y * val->ystep * val->padding); break; case 2: *((Uint16 *) pixels + offset) = (Uint16)*((Uint16 *) valsf->pixels + val->start + x * val->xstep + y * val->ystep * val->padding); break; case 3: /* TODO */ break; default: /* 4 bpp */ *((Uint32 *) pixels + offset) = *((Uint32 *) valsf->pixels + val->start + x * val->xstep + y * val->ystep * val->padding); break; } } } return 0; } static int _array_assign_sequence (PyPixelArray *array, Py_ssize_t _index, PyObject *val) { SDL_Surface *surface; Uint32 x = 0; Uint32 y = 0; int bpp; Uint8 *pixels; Uint32 color = 0; Uint32 *colorvals = NULL; Py_ssize_t offset = 0; Py_ssize_t seqsize = PySequence_Size (val); 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; /* 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; if ((Uint32)seqsize != ylen / ystep) { PyErr_SetString(PyExc_ValueError, "sequence size mismatch"); return -1; } if (seqsize == 1) { /* Single value assignment. */ offset = start + x + y * padding; switch (bpp) { case 1: *((Uint8 *) pixels + offset) = (Uint8) color; break; case 2: *((Uint16 *) pixels + offset) = (Uint16) color; break; case 3: /* TODO */ break; default: /* 4 bpp */ *((Uint32 *) pixels + offset) = color; break; } return 0; } /* Copy the values. */ colorvals = malloc (sizeof (Uint32) * seqsize); if (!colorvals) { PyErr_SetString(PyExc_ValueError, "could not copy pixels"); return -1; } for (offset = 0; offset < seqsize; offset++) { if (!_get_color_from_object (PySequence_Fast_GET_ITEM (val, offset), surface->format, &color)) { free (colorvals); return -1; } colorvals[offset] = color; } for (y = 0; y < ylen; y += ystep) { for (x = 0; x < xlen; x += xstep) { offset = start + x + y * padding; color = *colorvals++; switch (bpp) { case 1: *((Uint8 *) pixels + offset) = (Uint8) color; break; case 2: *((Uint16 *) pixels + offset) = (Uint16) color; break; case 3: /* TODO */ break; default: /* 4 bpp */ *((Uint32 *) pixels + offset) = color; break; } } } return 0; } /** * array[x] = ... */ static int _pxarray_ass_item (PyPixelArray *array, Py_ssize_t _index, PyObject *value) { 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; if (!_get_color_from_object (value, surface->format, &color)) { if (PyPixelArray_Check (value)) { PyErr_Clear (); /* _get_color_from_object */ return _array_assign_array (array, _index, (PyPixelArray *) value); } else if (PySequence_Check (value)) { PyErr_Clear (); /* _get_color_from_object */ return _array_assign_sequence (array, _index, value); } else /* Error already set by _get_color_from_object(). */ return -1; } if (array->xlen == 1) /* Single pixel access. */ { _set_single_pixel (pixels, bpp, array->start + _index * array->padding * array->ystep, color); return 0; } /* 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; /* Single value assignment. */ for (y = 0; y < ylen; y += ystep) { for (x = 0; x < xlen; x += xstep) { offset = start + x + y * padding; switch (bpp) { case 1: *((Uint8 *) pixels + offset) = (Uint8) color; break; case 2: *((Uint16 *) pixels + offset) = (Uint16) color; break; case 3: /* TODO */ break; default: /* 4 bpp */ *((Uint32 *) pixels + offset) = color; break; } } } return 0; } /** * array[x:y] = .... */ /* TODO: support: array[x:y] = [...] for 2D and 1D arrays array[x:y] = z for 2D and 1D arrays */ static int _pxarray_ass_slice (PyPixelArray *array, Py_ssize_t low, Py_ssize_t high, PyObject *value) { /* TODO */ PyErr_SetString (PyExc_NotImplementedError, "method not implemented"); return -1; } /** * x in array */ /* TODO: support: [...] in array for 2D arrays x in array for 1D and 2D arrays */ static int _pxarray_contains (PyPixelArray *array, PyObject *value) { SDL_Surface *surface; Uint32 x; Uint32 y; Py_ssize_t _index; Uint8 *pixels; int bpp; Uint32 color; surface = PySurface_AsSurface (array->surface); bpp = surface->format->BytesPerPixel; pixels = (Uint8 *) surface->pixels; if (!_get_color_from_object (value, surface->format, &color)) { /* TODO */ PyErr_SetString (PyExc_TypeError, "invalid color argument"); return -1; } switch (bpp) { case 1: for (x = 0; x < array->ylen; x += array->ystep) { for (y = 0; y < array->xlen; y += array->xstep) { _index = array->start + x + y * array->padding; if (*((Uint8 *) pixels + _index) == (Uint8) color) return 1; } } case 2: for (x = 0; x < array->ylen; x += array->ystep) { for (y = 0; y < array->xlen; y += array->xstep) { _index = array->start + x + y * array->padding; if (*((Uint16 *) pixels + _index) == (Uint16) color) return 1; } } break; case 3: /* TODO */ break; default: /* 4 bpp */ for (x = 0; x < array->ylen; x += array->ystep) { for (y = 0; y < array->xlen; y += array->xstep) { _index = array->start + x + y * array->padding; if (*((Uint32 *) pixels + _index) == color) return 1; } } break; } return 0; } /** * array += .... */ static PyObject* _pxarray_inplace_concat (PyPixelArray *array, PyObject *seq) { /* TODO */ return RAISE (PyExc_NotImplementedError, "method not implemented"); } /** * array *= ... */ static PyObject* _pxarray_inplace_repeat (PyPixelArray *array, Py_ssize_t n) { /* TODO */ return RAISE (PyExc_NotImplementedError, "method not implemented"); } /**** Mapping interfaces ****/ /** * Internally used parser function for the 2D slices: * array[x,y], array[:,:], ... */ /* static int */ /* _get_subslice (SDL_Surface *surface, PyObject *op, Py_ssize_t *start, */ /* Py_ssize_t *stop, Py_ssize_t *step) */ /* { */ /* *start = -1; */ /* *stop = -1; */ /* *step = -1; */ /* if (PyInt_Check (op)) */ /* { */ /* printf ("Found int\n"); */ /* /\* Plain index: array[x, *\/ */ /* *start = PyInt_AsLong (op); */ /* return 1; */ /* } */ /* else if (PyLong_Check (op)) */ /* { */ /* long long val = -1; */ /* /\* Plain index: array[x, *\/ */ /* printf ("Found long\n"); */ /* val = PyLong_AsLong (op); */ /* if ((val < INT_MIN) || (val > INT_MAX)) */ /* { */ /* PyErr_SetString(PyExc_ValueError, "index too big for array access"); */ /* return -1; */ /* } */ /* *start = (int) val; */ /* } */ /* else if (op == Py_Ellipsis) */ /* { */ /* /\* Operator is the ellipsis: array[..., *\/ */ /* printf ("Found ellipsis\n"); */ /* /\* TODO *\/ */ /* } */ /* else if (PySlice_Check (op)) */ /* { */ /* Py_ssize_t slicelen; */ /* /\* Operator is a slice: array[x::, *\/ */ /* printf ("Found slice\n"); */ /* if (PySlice_GetIndicesEx ((PySliceObject *) op, surface->w * surface->h, */ /* start, stop, step, &slicelen) < 0) */ /* { */ /* return 0; */ /* } */ /* } */ /* return 0; */ /* } */ /** * Slicing support for 1D and 2D access. * array[x,y] is only supported for 2D arrays. */ /* static PyObject* */ /* _pxarray_subscript (PyPixelArray *array, PyObject *op) */ /* { */ /* Py_ssize_t step; */ /* Py_ssize_t start; */ /* Py_ssize_t stop; */ /* SDL_Surface *surface = PySurface_AsSurface (array->surface); */ /* /\* Note: order matters here. */ /* * First check array[x,y], then array[x:y:z], then array[x] */ /* * Otherwise it'll fail. */ /* *\/ */ /* if (PySequence_Check (op)) */ /* { */ /* PyObject *sub; */ /* Py_ssize_t i; */ /* if (PySequence_Size (op) > 2) */ /* return RAISE (PyExc_IndexError, */ /* "too many indices for the 2D array"); */ /* for (i = 0; i < PySequence_Size (op); i++) */ /* { */ /* sub = PySequence_GetItem (op, i); */ /* if (!_get_subslice (surface, sub, &start, &stop, &step)) */ /* { */ /* /\* Error on retrieving the subslice. *\/ */ /* printf ("Error\n"); */ /* Py_DECREF (sub); */ /* return NULL; */ /* } */ /* if (stop == -1) */ /* { */ /* /\* Not an index *\/ */ /* printf ("Slice: %d:%d:%d\n", start, stop, step); */ /* } */ /* Py_DECREF (sub); */ /* } */ /* Py_DECREF (sub); */ /* } */ /* else if (PySlice_Check (op)) */ /* { */ /* /\* A slice *\/ */ /* PyObject *result; */ /* Py_ssize_t slicelen; */ /* if (PySlice_GetIndicesEx ((PySliceObject *) op, surface->w * surface->h, */ /* &start, &stop, &step, &slicelen) < 0) */ /* return NULL; */ /* if (slicelen < 0) /\* TODO: empty surface with 0x0 px? *\/ */ /* return NULL; */ /* /\* */ /* result = (PyObject *) _pxarray_new_internal */ /* (&PyPixelArray_Type, array->surface, (Uint32) start, (Uint32) stop, */ /* 1, step, 1, (PyObject *) array); */ /* *\/ */ /* return result; */ /* } */ /* else if (PyIndex_Check (op)) */ /* { */ /* /\* A simple index. *\/ */ /* Py_ssize_t i = PyNumber_AsSsize_t (op, PyExc_IndexError); */ /* if (i == -1 && PyErr_Occurred ()) */ /* return NULL; */ /* if (i < 0) */ /* i += surface->w * surface->h; */ /* return _pxarray_item (array, i); */ /* } */ /* return RAISE (PyExc_TypeError, */ /* "index must be an integer, sequence or slice"); */ /* } */ /* static int */ /* _pxarray_ass_subscript (PyPixelArray *array, PyObject* op, PyObject* value) */ /* { */ /* SDL_Surface *surface = PySurface_AsSurface (array->surface); */ /* if (PyIndex_Check (op)) */ /* { */ /* /\* A simple index. *\/ */ /* Py_ssize_t i = PyNumber_AsSsize_t (op, PyExc_IndexError); */ /* if (i == -1 && PyErr_Occurred ()) */ /* return -1; */ /* if (i < 0) */ /* i += surface->w * surface->h; */ /* return _pxarray_ass_item (array, i, value); */ /* } */ /* PyErr_SetString (PyExc_NotImplementedError, "method not implemented"); */ /* return -1; */ /* } */ /**** Buffer interfaces ****/ static Py_ssize_t _pxarray_getreadbuf (PyPixelArray *array, Py_ssize_t _index, const void **ptr) { 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? */ } 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; } 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; } static PyMethodDef surfarray_builtins[] = { { NULL, NULL, 0, NULL } }; PYGAME_EXPORT void initpixelarray (void) { PyObject *module; if (PyType_Ready (&PyPixelArray_Type) < 0) return; /* create the module */ module = Py_InitModule3 ("pixelarray", NULL, NULL); Py_INCREF (&PyPixelArray_Type); PyModule_AddObject (module, "PixelArray", (PyObject *) &PyPixelArray_Type); /*imported needed apis*/ import_pygame_base (); import_pygame_surface (); }
