Mercurial > pygame
view src/pixelarray.c @ 3194:9fcb7abf3185 default tip
Remove some gcc 4.7.2 compiler warnings
| author | Lenard Lindstrom <len-l@telus.net> |
|---|---|
| date | Tue, 23 Apr 2013 19:53:36 -0700 |
| parents | a76f2f499bbe |
| children |
line wrap: on
line source
/* pygame - Python Game Library Copyright (C) 2007-2008 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 */ #define PYGAMEAPI_PIXELARRAY_INTERNAL #include "pygame.h" #include "pgcompat.h" #include "doc/pixelarray_doc.h" #include "pgarrinter.h" #include "surface.h" #if PY_VERSION_HEX < 0x02050000 #define PyIndex_Check(op) 0 #endif struct _pixelarray_t; /* The array, like its surface, is in column-major (FORTRAN) order. This is the reverse of C's row-major order. All array descriptor fields are relative to the original surface data. The pixels field is adjusted for any offsets of the array view into the surface. If dim1 is 0 the array is one dimensional. */ typedef struct _pixelarray_t { 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 */ Py_ssize_t dim0; /* Shape 0 of array, in pixels */ Py_ssize_t dim1; /* Shape 1 of array, in pixels */ Py_ssize_t stride0; /* Offset, in bytes, between pixels within a row */ Py_ssize_t stride1; /* Offset, in bytes, between rows */ Uint8 *pixels; /* Start of array data */ struct _pixelarray_t *parent; /* Parent pixel array: NULL if no parent */ } PyPixelArray; static PyPixelArray *_pxarray_new_internal( PyTypeObject *type, PyObject *surface, PyPixelArray *parent, Uint8 *pixels, Py_ssize_t dim0, Py_ssize_t dim1, Py_ssize_t stride0, Py_ssize_t stride1); 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_get_itemsize(PyPixelArray *self, void *closure); static PyObject *_pxarray_get_shape(PyPixelArray *self, void *closure); static PyObject *_pxarray_get_strides(PyPixelArray *self, void *closure); static PyObject *_pxarray_get_ndim(PyPixelArray *self, void *closure); static PyObject *_pxarray_get_arraystruct(PyPixelArray *self, void *closure); static PyObject *_pxarray_get_pixelsaddress(PyPixelArray *self, void *closure); static PyObject *_pxarray_repr(PyPixelArray *array); static PyObject *_array_slice_internal( PyPixelArray *array, Py_ssize_t start, Py_ssize_t end, Py_ssize_t step); #if PY3 static void _pxarray_capsule_destr(PyObject *capsule); #endif /* Sequence methods */ static Py_ssize_t _pxarray_length(PyPixelArray *array); static PyObject *_pxarray_item(PyPixelArray *array, Py_ssize_t index); 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 _array_assign_slice( PyPixelArray *array, Py_ssize_t low, Py_ssize_t high, Uint32 color); 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); /* Mapping methods */ static int _get_subslice(PyObject *op, Py_ssize_t length, 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); static PyObject *_pxarray_subscript_internal( PyPixelArray *array, Py_ssize_t xstart, Py_ssize_t xstop, Py_ssize_t xstep, Py_ssize_t ystart, Py_ssize_t ystop, Py_ssize_t ystep); /* C API interfaces */ static PyObject* PyPixelArray_New(PyObject *surfobj); /* Incomplete forward declaration so we can use it in the methods included * below. */ static PyTypeObject PyPixelArray_Type; #define PyPixelArray_Check(o) \ (Py_TYPE (o) == (PyTypeObject *) &PyPixelArray_Type) #define SURFACE_EQUALS(x,y) \ (((PyPixelArray *)x)->surface == ((PyPixelArray *)y)->surface) #include "pixelarray_methods.c" /** * Methods, which are bound to the PyPixelArray type. */ static PyMethodDef _pxarray_methods[] = { { "compare", (PyCFunction)_compare, METH_VARARGS | METH_KEYWORDS, DOC_PIXELARRAYCOMPARE }, { "extract", (PyCFunction)_extract_color, METH_VARARGS | METH_KEYWORDS, DOC_PIXELARRAYEXTRACT }, { "make_surface", (PyCFunction)_make_surface, METH_NOARGS, DOC_PIXELARRAYMAKESURFACE }, { "replace", (PyCFunction)_replace_color, METH_VARARGS | METH_KEYWORDS, DOC_PIXELARRAYREPLACE }, { "transpose", (PyCFunction)_transpose, METH_NOARGS, DOC_PIXELARRAYTRANSPOSE }, { NULL, NULL, 0, NULL } }; #if PY3 static void Text_ConcatAndDel(PyObject **string, PyObject *newpart) { PyObject *result = 0; if (*string && newpart) { PyUnicode_Concat(*string, newpart); Py_DECREF(*string); Py_DECREF(newpart); } else { Py_XDECREF(*string); Py_XDECREF(newpart); } *string = result; } #else #define Text_ConcatAndDel PyString_ConcatAndDel #endif /** * Getters and setters for the PyPixelArray. */ static PyGetSetDef _pxarray_getsets[] = { { "__dict__", (getter)_pxarray_get_dict, 0, 0, 0 }, { "surface", (getter)_pxarray_get_surface, 0, DOC_PIXELARRAYSURFACE, 0 }, { "itemsize", (getter)_pxarray_get_itemsize, 0, DOC_PIXELARRAYITEMSIZE, 0 }, { "shape", (getter)_pxarray_get_shape, 0, DOC_PIXELARRAYSHAPE, 0 }, { "strides", (getter)_pxarray_get_strides, 0, DOC_PIXELARRAYSTRIDES, 0 }, { "ndim", (getter)_pxarray_get_ndim, 0, DOC_PIXELARRAYNDIM, 0 }, { "__array_struct__", (getter)_pxarray_get_arraystruct, 0, "Version 3", 0 }, { "_pixels_address", (getter)_pxarray_get_pixelsaddress, 0, "pixel buffer address (readonly)", 0 }, { 0, 0, 0, 0, 0 } }; /** * Sequence interface support for the PyPixelArray. * concat and repeat are not implemented due to the possible confusion * of their behaviour (see lists numpy array). */ static PySequenceMethods _pxarray_sequence = { (lenfunc)_pxarray_length, /*sq_length*/ 0, /*sq_concat*/ 0, /*sq_repeat*/ (ssizeargfunc)_pxarray_item, /*sq_item*/ 0, /*reserved*/ (ssizeobjargproc)_pxarray_ass_item, /*sq_ass_item*/ 0, /*reserved*/ (objobjproc)_pxarray_contains, /*sq_contains*/ 0, /*sq_inplace_concat*/ 0 /*sq_inplace_repeat*/ }; /** * Mapping interface support for the PyPixelArray. */ static PyMappingMethods _pxarray_mapping = { (lenfunc)_pxarray_length, /*mp_length*/ (binaryfunc)_pxarray_subscript, /*mp_subscript*/ (objobjargproc)_pxarray_ass_subscript, /*mp_ass_subscript*/ }; static PyTypeObject PyPixelArray_Type = { TYPE_HEAD (NULL, 0) "pygame.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 */ &_pxarray_mapping, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* 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 */ PySeqIter_New, /* 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 */ #ifndef __SYMBIAN32__ 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 */ #endif }; static PyPixelArray * _pxarray_new_internal(PyTypeObject *type, PyObject *surface, PyPixelArray *parent, Uint8 *pixels, Py_ssize_t dim0, Py_ssize_t dim1, Py_ssize_t stride0, Py_ssize_t stride1) { PyPixelArray *self; self = (PyPixelArray *)type->tp_alloc(type, 0); if (!self) { return 0; } if (!parent) { if (!surface) { Py_TYPE(self)->tp_free((PyObject *)self); PyErr_SetString(PyExc_SystemError, "Pygame internal error in _pxarray_new_internal: " "no parent or surface."); return 0; } self->parent = 0; self->surface = surface; Py_INCREF(surface); self->lock = PySurface_LockLifetime(surface, (PyObject *)self); if (!self->lock) { Py_DECREF(surface); Py_TYPE(self)->tp_free((PyObject *)self); return 0; } } else { self->parent = parent; Py_INCREF(parent); surface = parent->surface; self->surface = surface; Py_INCREF(surface); self->lock = parent->lock; Py_INCREF(self->lock); } self->dim0 = dim0; self->dim1 = dim1; self->stride0 = stride0; self->stride1 = stride1; self->pixels = pixels; self->weakrefs = 0; self->dict = 0; return self; } /** * Creates a new PyPixelArray. */ static PyObject * _pxarray_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *surfobj; SDL_Surface *surf; Py_ssize_t dim0; Py_ssize_t dim1; Py_ssize_t stride0; Py_ssize_t stride1; Uint8 *pixels; if (!PyArg_ParseTuple(args, "O!", &PySurface_Type, &surfobj)) { return 0; } surf = PySurface_AsSurface(surfobj); dim0 = (Py_ssize_t)surf->w; dim1 = (Py_ssize_t)surf->h; stride0 = (Py_ssize_t)surf->format->BytesPerPixel; stride1 = (Py_ssize_t)surf->pitch; pixels = surf->pixels; if (stride0 < 1 || stride0 > 4) { return RAISE(PyExc_ValueError, "unsupport bit depth for reference array"); } return (PyObject *)_pxarray_new_internal(type, surfobj, 0, pixels, dim0, dim1, stride0, stride1); } /** * Deallocates the PyPixelArray and its members. */ static void _pxarray_dealloc(PyPixelArray *self) { if (self->weakrefs) { PyObject_ClearWeakRefs ((PyObject *) self); } Py_XDECREF(self->lock); Py_XDECREF(self->parent); Py_XDECREF(self->dict); Py_DECREF(self->surface); Py_TYPE(self)->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 0; } } Py_INCREF(self->dict); return self->dict; } /** * Getter for PixelArray.surface */ static PyObject* _pxarray_get_surface(PyPixelArray *self, void *closure) { Py_INCREF(self->surface); return self->surface; } /** * Getter for PixelArray.itemsize * (pixel size in bytes) */ static PyObject * _pxarray_get_itemsize(PyPixelArray *self, void *closure) { SDL_Surface *surf = PySurface_AsSurface(self->surface); return PyInt_FromLong((long)surf->format->BytesPerPixel); } /** * Getter for PixelArray.shape */ static PyObject * _pxarray_get_shape(PyPixelArray *self, void *closure) { if (self->dim1) { return Py_BuildValue("(nn)", self->dim0, self->dim1); } return Py_BuildValue("(n)", self->dim0); } /** * Getter for PixelArray.strides */ static PyObject * _pxarray_get_strides(PyPixelArray *self, void *closure) { if (self->dim1) { return Py_BuildValue("(nn)", self->stride0, self->stride1); } return Py_BuildValue("(n)", self->stride0); } /** * Getter for PixelArray.ndim */ static PyObject * _pxarray_get_ndim(PyPixelArray *self, void *closure) { return PyInt_FromLong(self->dim1 ? 2L : 1L); } /** * Getter for PixelArray.__array_struct__ * (array struct interface) */ static PyObject * _pxarray_get_arraystruct(PyPixelArray *self, void *closure) { typedef struct { PyArrayInterface inter; Py_intptr_t shape_mem[2]; Py_intptr_t strides_mem[2]; } Interface; int itemsize = (int)PySurface_AsSurface(self->surface)->format->BytesPerPixel; Interface *allocation; PyArrayInterface *inter; PyObject *capsule; allocation = PyMem_New(Interface, 1); if (!allocation) { return PyErr_NoMemory(); } inter = (PyArrayInterface *)allocation; inter->shape = allocation->shape_mem; inter->strides = allocation->strides_mem; #if PY3 capsule = PyCapsule_New(inter, 0, _pxarray_capsule_destr); #else capsule = PyCObject_FromVoidPtr(inter, PyMem_Free); #endif if (!capsule) { PyMem_Free(inter); return 0; } inter->two = 2; inter->typekind = 'u'; inter->itemsize = itemsize; inter->flags = PAI_ALIGNED | PAI_NOTSWAPPED | PAI_WRITEABLE | PAI_FORTRAN; inter->descr = 0; inter->nd = self->dim1 ? 2 : 1; inter->shape[0] = (Py_intptr_t)self->dim0; inter->shape[1] = (Py_intptr_t)self->dim1; inter->strides[0] = (Py_intptr_t)self->stride0; inter->strides[1] = (Py_intptr_t)self->stride1; if (self->stride0 == itemsize && (!self->dim1 || self->stride1 == self->dim0 * itemsize)) { inter->flags |= PAI_CONTIGUOUS; } inter->data = self->pixels; return capsule; } #if PY3 static void _pxarray_capsule_destr (PyObject *capsule) { PyMem_Free (PyCapsule_GetPointer (capsule, 0)); } #endif /** * Getter for PixelArray._pixels_address * (address of the array's pointer into its surface's pixel data) */ static PyObject * _pxarray_get_pixelsaddress(PyPixelArray *self, void *closure) { void *address = self->pixels; #if SIZEOF_VOID_P > SIZEOF_LONG return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)address); #else return PyLong_FromUnsignedLong((unsigned long)address); #endif } /**** Methods ****/ /** * repr(PixelArray) */ static PyObject * _pxarray_repr(PyPixelArray *array) { SDL_Surface *surf = PySurface_AsSurface(array->surface); PyObject *string; int bpp; Uint8 *pixels = array->pixels; int ndim = array->dim1 ? 2 : 1; Py_ssize_t dim0 = array->dim0; Py_ssize_t dim1 = array->dim1 ? array->dim1 : 1; Py_ssize_t stride0 = array->stride0; Py_ssize_t stride1 = array->stride1; Uint32 pixel; Py_ssize_t x; Py_ssize_t y; Uint8 *pixelrow; Uint8 *pixel_p; bpp = surf->format->BytesPerPixel; string = Text_FromUTF8 ("PixelArray("); if (!string) { return 0; } pixelrow = pixels; if (ndim == 2) { Text_ConcatAndDel(&string, Text_FromUTF8("[")); if (!string) { return 0; } } switch (bpp) { case 1: for (y = 0; y < dim1; ++y) { Text_ConcatAndDel(&string, Text_FromUTF8("\n [")); if (!string) { return 0; } pixel_p = pixelrow; for (x = 0; x < dim0 - 1; ++x) { Text_ConcatAndDel(&string, Text_FromFormat("%ld, ", (long)*pixel_p)); if (!string) { return 0; } pixel_p += stride0; } Text_ConcatAndDel(&string, Text_FromFormat("%ld]", (long)*pixel_p)); if (!string) { return 0; } pixelrow += stride1; } break; case 2: for (y = 0; y < dim1; ++y) { Text_ConcatAndDel(&string, Text_FromUTF8("\n [")); if (!string) { return 0; } pixel_p = pixelrow; for (x = 0; x < dim0 - 1; ++x) { Text_ConcatAndDel(&string, Text_FromFormat("%ld, ", (long)*(Uint16 *)pixel_p)); if (!string) { return 0; } pixel_p += stride0; } Text_ConcatAndDel(&string, Text_FromFormat("%ld]", (long)*(Uint16 *)pixel_p)); if (string == NULL) { return NULL; } pixelrow += stride1; } break; case 3: for (y = 0; y < dim1; ++y) { Text_ConcatAndDel(&string, Text_FromUTF8("\n [")); pixel_p = pixelrow; for (x = 0; x < dim0 - 1; ++x) { #if SDL_BYTEORDER == SDL_LIL_ENDIAN pixel = (pixel_p[0]) + (pixel_p[1] << 8) + (pixel_p[2] << 16); #else pixel = (pixel_p[2]) + (pixel_p[1] << 8) + (pixel_p[0] << 16); #endif Text_ConcatAndDel(&string, Text_FromFormat("%ld, ", (long)pixel)); if (!string) { return 0; } pixel_p += stride0; } #if SDL_BYTEORDER == SDL_LIL_ENDIAN pixel = (pixel_p[0]) + (pixel_p[1] << 8) + (pixel_p[2] << 16); #else pixel = (pixel_p[2]) + (pixel_p[1] << 8) + (pixel_p[0] << 16); #endif Text_ConcatAndDel(&string, Text_FromFormat("%ld]", (long)pixel)); if (!string) { return 0; } pixelrow += stride1; } break; default: /* case 4: */ for (y = 0; y < dim1; ++y) { Text_ConcatAndDel(&string, Text_FromUTF8("\n [")); if (!string) { return 0; } pixel_p = pixelrow; for (x = 0; x < dim0 - 1; ++x) { Text_ConcatAndDel(&string, Text_FromFormat("%ld, ", (long)*(Uint32 *)pixel_p)); if (!string) { return 0; } pixel_p += stride0; } Text_ConcatAndDel(&string, Text_FromFormat("%ld]", (long)*(Uint32 *)pixel_p)); if (string == NULL) { return NULL; } pixelrow += stride1; } break; } if (ndim == 2) { Text_ConcatAndDel(&string, Text_FromUTF8 ("]\n)")); } else { Text_ConcatAndDel (&string, Text_FromUTF8 ("\n)")); } return string; } static PyObject * _pxarray_subscript_internal(PyPixelArray *array, Py_ssize_t xstart, Py_ssize_t xstop, Py_ssize_t xstep, Py_ssize_t ystart, Py_ssize_t ystop, Py_ssize_t ystep) { /* Special case: if xstep or ystep are zero, then the corresponding * dimension is removed. If both are zero, then a single integer * pixel value is returned. */ Py_ssize_t dim0; Py_ssize_t dim1; Py_ssize_t stride0; Py_ssize_t stride1; Uint8 *pixels; Py_ssize_t absxstep = ABS(xstep); Py_ssize_t absystep = ABS(ystep); Py_ssize_t dx = xstop - xstart; Py_ssize_t dy = ystop - ystart; if (!array->dim1) { ystart = 0; ystop = 1; ystep = 0; } if (!(xstep || ystep)) { return _get_single_pixel(array, xstart, ystart); } if (xstep) { dim0 = (ABS(dx) + absxstep - 1) / absxstep; stride0 = array->stride0 * xstep; } else { /* Move dimension 2 into 1 */ dim0 = (ABS(dy) + absystep - 1) / absystep; stride0 = array->stride1 * ystep; } if (xstep && ystep) { dim1 = (ABS(dy) + absystep - 1) / absystep; stride1 = array->stride1 * ystep; } else { /* Only a one dimensional array */ dim1 = 0; stride1 = 0; } pixels = array->pixels + xstart * array->stride0 + ystart * array->stride1; return (PyObject *)_pxarray_new_internal(&PyPixelArray_Type, 0, array, pixels, dim0, dim1, stride0, stride1); } /** * Creates a 2D slice of the array. */ static PyObject * _array_slice_internal(PyPixelArray *array, Py_ssize_t start, Py_ssize_t end, Py_ssize_t step) { if (end == start) { return RAISE(PyExc_IndexError, "array size must not be 0"); } if (start >= array->dim0) { return RAISE(PyExc_IndexError, "array index out of range"); } return _pxarray_subscript_internal(array, start, end, step, 0, array->dim1, 1); } /**** Sequence interfaces ****/ /** * len (array) */ static Py_ssize_t _pxarray_length(PyPixelArray *array) { return array->dim0; } /** * array[x] */ static PyObject * _pxarray_item(PyPixelArray *array, Py_ssize_t index) { if (index < 0) { index = array->dim0 - index; if (index < 0) { return RAISE(PyExc_IndexError, "array index out of range"); } } if (index >= array->dim0) { return RAISE(PyExc_IndexError, "array index out of range"); } return _pxarray_subscript_internal(array, index, 0, 0, 0, array->dim1, 1); } static int _array_assign_array(PyPixelArray *array, Py_ssize_t low, Py_ssize_t high, PyPixelArray *val) { SDL_Surface *surf = PySurface_AsSurface(array->surface); Py_ssize_t dim0 = ABS(high - low); Py_ssize_t dim1 = array->dim1; Py_ssize_t stride0 = high >= low ? array->stride0 : -array->stride0; Py_ssize_t stride1 = array->stride1; Uint8 *pixels = array->pixels + low * array->stride0; int bpp; Py_ssize_t val_dim0 = val->dim0; Py_ssize_t val_dim1 = val->dim1; Py_ssize_t val_stride0 = val->stride0; Py_ssize_t val_stride1 = val->stride1; Uint8 *val_pixels = val->pixels; SDL_Surface *val_surf = PySurface_AsSurface(val->surface); int val_bpp; Uint8 *pixelrow; Uint8 *pixel_p; Uint8 *val_pixelrow; Uint8 *val_pixel_p; Uint8 *copied_pixels = 0; Py_ssize_t x; Py_ssize_t y; int sizes_match = 0; /* Broadcast length 1 val dimensions.*/ if (val_dim0 == 1) { val_dim0 = dim0; val_stride0 = 0; } if (val_dim1 == 1) { val_dim1 = dim1; val_stride1 = 0; } if (val_dim1) { sizes_match = (dim0 == val_dim0 && dim1 == val_dim1); } else if (dim1) { sizes_match = (dim1 == val_dim0); } else { sizes_match = (dim0 == val_dim0); } if (!sizes_match) { /* Bounds do not match. */ PyErr_SetString(PyExc_ValueError, "array sizes do not match"); return -1; } bpp = surf->format->BytesPerPixel; val_bpp = val_surf->format->BytesPerPixel; if (val_bpp != bpp) { /* bpp do not match. We cannot guarantee that the padding and columns * would be set correctly. */ PyErr_SetString(PyExc_ValueError, "bit depths do not match"); return -1; } /* If we reassign the same array, we need to copy the pixels * first. */ if (SURFACE_EQUALS(array, val)) { /* We assign a different view or so. Copy the source buffer. */ size_t size = val_surf->h * val_surf->pitch; int val_offset = val_pixels - (Uint8 *)val_surf->pixels; copied_pixels = (Uint8 *)malloc(size); if (!copied_pixels) { PyErr_NoMemory(); return -1; } val_pixels = (Uint8 *)memcpy(copied_pixels, val_surf->pixels, size) + val_offset; } if (!dim1) { dim1 = 1; } pixelrow = pixels; val_pixelrow = val_pixels; switch (bpp) { case 1: for (y = 0; y < dim1; ++y) { pixel_p = pixelrow; val_pixel_p = val_pixelrow; for (x = 0; x < dim0; ++x) { *pixel_p = *val_pixel_p; pixel_p += stride0; val_pixel_p += val_stride0; } pixelrow += stride1; val_pixelrow += val_stride1; } break; case 2: for (y = 0; y < dim1; ++y) { pixel_p = pixelrow; val_pixel_p = val_pixelrow; for (x = 0; x < dim0; ++x) { *((Uint16 *)pixel_p) = *((Uint16 *)val_pixel_p); pixel_p += stride0; val_pixel_p += val_stride0; } pixelrow += stride1; val_pixelrow += val_stride1; } break; case 3: { #if (SDL_BYTEORDER == SDL_LIL_ENDIAN) Uint32 Roffset = surf->format->Rshift >> 3; Uint32 Goffset = surf->format->Gshift >> 3; Uint32 Boffset = surf->format->Bshift >> 3; Uint32 vRoffset = val_surf->format->Rshift >> 3; Uint32 vGoffset = val_surf->format->Gshift >> 3; Uint32 vBoffset = val_surf->format->Bshift >> 3; #else Uint32 Roffset = 2 - surf->format->Rshift >> 3; Uint32 Goffset = 2 - surf->format->Gshift >> 3; Uint32 Boffset = 2 - surf->format->Bshift >> 3; Uint32 vRoffset = 2 - val_surf->format->Rshift >> 3; Uint32 vGoffset = 2 - val_surf->format->Gshift >> 3; Uint32 vBoffset = 2 - val_surf->format->Bshift >> 3; #endif for (y = 0; y < dim1; ++y) { pixel_p = pixelrow; val_pixel_p = val_pixelrow; for (x = 0; x < dim0; ++x) { pixel_p[Roffset] = val_pixel_p[vRoffset]; pixel_p[Goffset] = val_pixel_p[vGoffset]; pixel_p[Boffset] = val_pixel_p[vBoffset]; pixel_p += stride0; val_pixel_p += val_stride0; } pixelrow += stride1; val_pixelrow += val_stride1; } } break; default: /* case 4: */ for (y = 0; y < dim1; ++y) { pixel_p = pixelrow; val_pixel_p = val_pixelrow; for (x = 0; x < dim0; ++x) { *((Uint32 *)pixel_p) = *((Uint32 *)val_pixel_p); pixel_p += stride0; val_pixel_p += val_stride0; } pixelrow += stride1; val_pixelrow += val_stride1; } break; } if (copied_pixels) { free(copied_pixels); } return 0; } static int _array_assign_sequence(PyPixelArray *array, Py_ssize_t low, Py_ssize_t high, PyObject *val) { SDL_Surface *surf = PySurface_AsSurface(array->surface); SDL_PixelFormat *format; Py_ssize_t dim0 = ABS (high - low); Py_ssize_t dim1 = array->dim1; Py_ssize_t stride0 = high >= low ? array->stride0 : -array->stride0; Py_ssize_t stride1 = array->stride1; Uint8 *pixels = array->pixels + low * array->stride0; int bpp; Py_ssize_t val_dim0 = PySequence_Size(val); Uint32 *val_colors; Uint8 *pixelrow; Uint8 *pixel_p; Uint32 *val_color_p; Py_ssize_t x; Py_ssize_t y; if (val_dim0 != dim0) { PyErr_SetString(PyExc_ValueError, "sequence size mismatch"); return -1; } format = surf->format; bpp = format->BytesPerPixel; if (!dim1) { dim1 = 1; } /* Copy the values. */ val_colors = malloc(sizeof(Uint32) * val_dim0); if (!val_colors) { PyErr_NoMemory(); return -1; } for (x = 0; x < val_dim0; ++x) { if (!_get_color_from_object(PySequence_Fast_GET_ITEM(val, x), format, (val_colors + x))) { free (val_colors); return -1; } } pixelrow = pixels; Py_BEGIN_ALLOW_THREADS; switch (bpp) { case 1: for (y = 0; y < dim1; ++y) { pixel_p = pixelrow; val_color_p = val_colors; for (x = 0; x < dim0; ++x) { *pixel_p = (Uint8)*val_color_p; pixel_p += stride0; ++val_color_p; } pixelrow += stride1; } break; case 2: for (y = 0; y < dim1; ++y) { pixel_p = pixelrow; val_color_p = val_colors; for (x = 0; x < dim0; ++x) { *((Uint16 *)pixel_p) = (Uint16)*val_color_p; pixel_p += stride0; ++val_color_p; } pixelrow += stride1; } break; case 3: { #if (SDL_BYTEORDER == SDL_LIL_ENDIAN) Uint32 Roffset = surf->format->Rshift >> 3; Uint32 Goffset = surf->format->Gshift >> 3; Uint32 Boffset = surf->format->Bshift >> 3; #else Uint32 Roffset = 2 - surf->format->Rshift >> 3; Uint32 Goffset = 2 - surf->format->Gshift >> 3; Uint32 Boffset = 2 - surf->format->Bshift >> 3; #endif for (y = 0; y < dim1; ++y) { pixel_p = pixelrow; val_color_p = val_colors; for (x = 0; x < dim0; ++x) { pixel_p[Roffset] = (Uint8)(*val_color_p >> 16); pixel_p[Goffset] = (Uint8)(*val_color_p >> 8); pixel_p[Boffset] = (Uint8)*val_color_p; pixel_p += stride0; ++val_color_p; } pixelrow += stride1; } } break; default: /* case 4: */ for (y = 0; y < dim1; ++y) { pixel_p = pixelrow; val_color_p = val_colors; for (x = 0; x < dim0; ++x) { *((Uint32 *)pixel_p) = *val_color_p; pixel_p += stride0; ++val_color_p; } pixelrow += stride1; } break; } Py_END_ALLOW_THREADS; free(val_colors); return 0; } static int _array_assign_slice(PyPixelArray *array, Py_ssize_t low, Py_ssize_t high, Uint32 color) { SDL_Surface *surf = PySurface_AsSurface(array->surface); Py_ssize_t dim0 = ABS (high - low); Py_ssize_t dim1 = array->dim1; Py_ssize_t stride0 = high >= low ? array->stride0 : -array->stride0; Py_ssize_t stride1 = array->stride1; Uint8 *pixels = array->pixels + low * array->stride0; int bpp; Uint8 *pixelrow; Uint8 *pixel_p; Py_ssize_t x; Py_ssize_t y; bpp = surf->format->BytesPerPixel; if (!dim1) { dim1 = 1; } pixelrow = pixels; Py_BEGIN_ALLOW_THREADS; switch (bpp) { case 1: { Uint8 c = (Uint8)color; for (y = 0; y < dim1; ++y) { pixel_p = pixelrow; for (x = 0; x < dim0; ++x) { *pixel_p = c; pixel_p += stride0; } pixelrow += stride1; } } break; case 2: { Uint16 c = (Uint16)color; for (y = 0; y < dim1; ++y) { pixel_p = pixelrow; for (x = 0; x < dim0; ++x) { *((Uint16 *)pixel_p) = c; pixel_p += stride0; } pixelrow += stride1; } } break; case 3: { #if (SDL_BYTEORDER == SDL_LIL_ENDIAN) Uint32 Roffset = surf->format->Rshift >> 3; Uint32 Goffset = surf->format->Gshift >> 3; Uint32 Boffset = surf->format->Bshift >> 3; #else Uint32 Roffset = 2 - surf->format->Rshift >> 3; Uint32 Goffset = 2 - surf->format->Gshift >> 3; Uint32 Boffset = 2 - surf->format->Bshift >> 3; #endif Uint8 r = (Uint8)(color >> 16); Uint8 g = (Uint8)(color >> 8); Uint8 b = (Uint8)(color); for (y = 0; y < dim1; ++y) { pixel_p = pixelrow; for (x = 0; x < dim0; ++x) { pixel_p[Roffset] = r; pixel_p[Goffset] = g; pixel_p[Boffset] = b; pixel_p += stride0; } pixelrow += stride1; } } break; default: /* case 4: */ for (y = 0; y < dim1; ++y) { pixel_p = pixelrow; for (x = 0; x < dim0; ++x) { *((Uint32 *)pixel_p) = color; pixel_p += stride0; } pixelrow += stride1; } break; } Py_END_ALLOW_THREADS; return 0; } /** * array[x] = ... */ static int _pxarray_ass_item(PyPixelArray *array, Py_ssize_t index, PyObject *value) { SDL_Surface *surf = PySurface_AsSurface(array->surface); Py_ssize_t y = 0; int bpp; Uint8 *pixels = array->pixels; Uint8 *pixel_p; Uint32 color = 0; Py_ssize_t dim0 = array->dim0; Py_ssize_t dim1 = array->dim1; Py_ssize_t stride0 = array->stride0; Py_ssize_t stride1 = array->stride1; PyPixelArray *tmparray = 0; int retval; bpp = surf->format->BytesPerPixel; if (!_get_color_from_object(value, surf->format, &color)) { if (PyTuple_Check (value)) { return -1; } if (PyPixelArray_Check(value)) { PyErr_Clear(); /* _get_color_from_object */ return _array_assign_array(array, index, index + 1, (PyPixelArray *)value); } else if (PySequence_Check(value)) { PyErr_Clear(); /* _get_color_from_object */ tmparray = (PyPixelArray *) _pxarray_subscript_internal(array, index, 0, 0, 0, array->dim1, 1); if (!tmparray) { return -1; } retval = _array_assign_sequence(tmparray, 0, tmparray->dim0, value); Py_DECREF(tmparray); return retval; } else { /* Error already set by _get_color_from_object(). */ return -1; } } if (index < 0) { index += dim0; if (index < 0) { PyErr_SetString(PyExc_IndexError, "array index out of range"); return -1; } } if (index >= dim0) { PyErr_SetString(PyExc_IndexError, "array index out of range"); } pixels += index * stride0; pixel_p = pixels; if (!dim1) { dim1 = 1; } Py_BEGIN_ALLOW_THREADS; /* Single value assignment. */ switch (bpp) { case 1: for (y = 0; y < dim1; ++y) { *((Uint8 *)pixel_p) = (Uint8)color; pixel_p += stride1; } break; case 2: for (y = 0; y < dim1; ++y) { *((Uint16 *)pixel_p) = (Uint16)color; pixel_p += stride1; } break; case 3: { #if (SDL_BYTEORDER == SDL_LIL_ENDIAN) Uint32 Roffset = surf->format->Rshift >> 3; Uint32 Goffset = surf->format->Gshift >> 3; Uint32 Boffset = surf->format->Bshift >> 3; #else Uint32 Roffset = 2 - (surf->format->Rshift >> 3); Uint32 Goffset = 2 - (surf->format->Gshift >> 3); Uint32 Boffset = 2 - (surf->format->Bshift >> 3); #endif for (y = 0; y < dim1; ++y) { pixel_p[Roffset] = (Uint8)(color >> 16); pixel_p[Goffset] = (Uint8)(color >> 8); pixel_p[Boffset] = (Uint8)color; pixel_p += stride1; } break; } default: /* case 4: */ for (y = 0; y < dim1; ++y) { *((Uint32 *)pixel_p) = color; pixel_p += stride1; } break; } Py_END_ALLOW_THREADS; return 0; } /** * array[x:y] = .... */ static int _pxarray_ass_slice(PyPixelArray *array, Py_ssize_t low, Py_ssize_t high, PyObject *value) { SDL_Surface *surf = PySurface_AsSurface(array->surface); Uint32 color; if (low < 0) { low = 0; } else if (low > (Sint32)array->dim0) { low = array->dim0; } if (high < low) { high = low; } else if (high > (Sint32)array->dim0) { high = array->dim0; } if (PyPixelArray_Check(value)) { return _array_assign_array(array, low, high, (PyPixelArray *)value); } if (_get_color_from_object(value, surf->format, &color)) { return _array_assign_slice(array, low, high, color); } if (PyTuple_Check (value)) { return -1; } PyErr_Clear(); /* In case _get_color_from_object set it */ if (PySequence_Check(value)) { return _array_assign_sequence(array, low, high, value); } return 0; } /** * x in array */ static int _pxarray_contains(PyPixelArray *array, PyObject *value) { SDL_Surface *surf = PySurface_AsSurface(array->surface); Py_ssize_t dim0 = array->dim0; Py_ssize_t dim1 = array->dim1; Py_ssize_t stride0 = array->stride0; Py_ssize_t stride1 = array->stride1; Uint8 *pixels = array->pixels; int bpp; Uint32 color; Uint8 *pixelrow; Uint8 *pixel_p; Py_ssize_t x; Py_ssize_t y; int found = 0; bpp = surf->format->BytesPerPixel; if (!_get_color_from_object(value, surf->format, &color)) { return -1; } if (!dim1) { dim1 = 1; } pixelrow = pixels; Py_BEGIN_ALLOW_THREADS; switch (bpp) { case 1: { Uint8 c = (Uint8)color; for (y = 0; !found && y < dim1; ++y) { pixel_p = pixelrow; for (x = 0; !found && x < dim0; ++x) { found = *pixel_p == c ? 1 : 0; pixel_p += stride0; } pixelrow += stride1; } } break; case 2: { Uint16 c = (Uint16)color; for (y = 0; !found && y < dim1; ++y) { pixel_p = pixelrow; for (x = 0; !found && x < dim0; ++x) { found = *((Uint16 *)pixel_p) == c ? 1 : 0; pixel_p += stride0; } pixelrow += stride1; } } break; case 3: for (y = 0; !found && y < dim1; ++y) { pixel_p = pixelrow; for (x = 0; !found && x < dim0; ++x) { #if SDL_BYTEORDER == SDL_LIL_ENDIAN found = (((Uint32)pixel_p[0]) + ((Uint32)pixel_p[1] << 8) + ((Uint32)pixel_p[2] << 16) ) == color; #else found = (((Uint32)pixel_p[2]) + ((Uint32)pixel_p[1] << 8) + ((Uint32)pixel_p[0] << 16) ) == color; #endif pixel_p += stride0; } pixelrow += stride1; } break; default: /* case 4: */ for (y = 0; !found && y < dim1; ++y) { pixel_p = pixelrow; for (x = 0; !found && x < dim0; ++x) { found = *((Uint32 *)pixel_p) == color ? 1 : 0; pixel_p += stride0; } pixelrow += stride1; } break; } Py_END_ALLOW_THREADS; return found; } /**** Mapping interfaces ****/ /** * Internally used parser function for the 2D slices: * array[x,y], array[:,:], ... */ static int _get_subslice(PyObject *op, Py_ssize_t length, Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step) { /* Special case: return step as 0 for an integer op. */ *start = -1; *stop = -1; *step = -1; if (PySlice_Check(op)) { Py_ssize_t slicelen; /* Operator is a slice: array[x::, */ if (Slice_GET_INDICES_EX(op, length, start, stop, step, &slicelen)) { return -1; } } else if (PyInt_Check(op)) { /* Plain index: array[x, */ *start = PyInt_AsLong(op); if (*start < 0) { *start += length; } if (*start >= length || *start < 0) { PyErr_SetString(PyExc_IndexError, "invalid index"); return -1; } *stop = (*start) + 1; *step = 0; } else if (PyLong_Check(op)) { long long val = -1; /* Plain index: array[x, */ 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; if (*start < 0) { *start += length; } if (*start >= length || *start < 0) { PyErr_SetString(PyExc_IndexError, "invalid index"); return -1; } *stop = (*start) + 1; *step = 0; } /* No errors. */ 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 dim0 = array->dim0; Py_ssize_t dim1 = array->dim1; /* 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 *obj; Py_ssize_t size = PySequence_Size(op); Py_ssize_t xstart, xstop, xstep; Py_ssize_t ystart, ystop, ystep; if (size == 0) { /* array[,], array[()] ... */ Py_INCREF(array); return (PyObject *)array; } if (size > 2 || (size == 2 && !dim1)) { return RAISE(PyExc_IndexError, "too many indices for the array"); } obj = PySequence_Fast_GET_ITEM(op, 0); if (obj == Py_Ellipsis || obj == Py_None) { /* Operator is the ellipsis or None * array[...,XXX], array[None,XXX] */ xstart = 0; xstop = dim0; xstep = 1; } else if (_get_subslice(obj, dim0, &xstart, &xstop, &xstep)) { /* Error on retrieving the subslice. */ return 0; } if (size == 2) { obj = PySequence_Fast_GET_ITEM(op, 1); if (obj == Py_Ellipsis || obj == Py_None) { /* Operator is the ellipsis or None * array[XXX,...], array[XXX,None] */ ystart = 0; ystop = dim1; ystep = 1; } else if (_get_subslice(obj, dim1, &ystart, &ystop, &ystep)) { /* Error on retrieving the subslice. */ return 0; } } else { ystart = 0; ystop = dim1; ystep = 1; } /* Null value? */ if (xstart == xstop || ystart == ystop) { Py_RETURN_NONE; } return _pxarray_subscript_internal(array, xstart, xstop, xstep, ystart, ystop, ystep); } else if (op == Py_Ellipsis) { Py_INCREF(array); return (PyObject *)array; } else if (PySlice_Check(op)) { /* A slice */ Py_ssize_t slicelen; Py_ssize_t step; Py_ssize_t start; Py_ssize_t stop; if (Slice_GET_INDICES_EX(op, dim0, &start, &stop, &step, &slicelen)) { return 0; } if (slicelen < 0) { return RAISE(PyExc_IndexError, "Unable to handle negative slice"); } if (slicelen == 0) { Py_RETURN_NONE; } return _pxarray_subscript_internal(array, start, stop, step, 0, dim1, 1); } else if (PyIndex_Check(op) || PyInt_Check(op) || PyLong_Check(op)) { Py_ssize_t i; #if PY_VERSION_HEX >= 0x02050000 PyObject *val = PyNumber_Index (op); if (!val) { return 0; } /* A simple index. */ i = PyNumber_AsSsize_t(val, PyExc_IndexError); #else i = PyInt_Check(op) ? PyInt_AsLong(op) : PyLong_AsLong(op); #endif if (i == -1 && PyErr_Occurred()) { return 0; } if (i < 0) { i += dim0; } if (i < 0 || i >= dim0) { return RAISE(PyExc_IndexError, "array index out of range"); } return _pxarray_subscript_internal(array, i, i + 1, 0, 0, dim1, 1); } return RAISE(PyExc_TypeError, "index must be an integer, sequence or slice"); } static int _pxarray_ass_subscript(PyPixelArray *array, PyObject* op, PyObject* value) { /* TODO: by time we can make this faster by avoiding the creation of * temporary subarrays. */ Py_ssize_t dim0 = array->dim0; Py_ssize_t dim1 = array->dim1; /* 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)) { PyPixelArray *tmparray; PyObject *obj; Py_ssize_t size = PySequence_Size(op); Py_ssize_t xstart, xstop, xstep; Py_ssize_t ystart, ystop, ystep; int retval; if (size > 2 || (size == 2 && !dim1)) { PyErr_SetString(PyExc_IndexError, "too many indices for the array"); return -1; } obj = PySequence_Fast_GET_ITEM(op, 0); if (obj == Py_Ellipsis || obj == Py_None) { /* Operator is the ellipsis or None * array[...,XXX], array[None,XXX] */ xstart = 0; xstop = dim0; xstep = 1; } else if (_get_subslice(obj, dim0, &xstart, &xstop, &xstep)) { /* Error on retrieving the subslice. */ return -1; } if (size == 2) { obj = PySequence_Fast_GET_ITEM(op, 1); if (obj == Py_Ellipsis || obj == Py_None) { /* Operator is the ellipsis or None * array[XXX,...], array[XXX,None] */ ystart = 0; ystop = dim1; ystep = 1; } else if (_get_subslice(obj, dim1, &ystart, &ystop, &ystep)) { /* Error on retrieving the subslice. */ return -1; } } else { ystart = 0; ystop = dim1; ystep = 1; } /* Null value? Do nothing then. */ if (xstart == xstop || ystart == ystop) { return 0; } /* Single value? */ if (ABS(xstop - xstart) == 1 && ABS(ystop - ystart) == 1) { tmparray = (PyPixelArray *) _pxarray_subscript_internal(array, xstart, xstart + 1, 1, ystart, ystart + 1, 1); if (!tmparray) { return -1; } retval = _pxarray_ass_item(tmparray, 0, value); Py_DECREF(tmparray); return retval; } tmparray = (PyPixelArray *) _pxarray_subscript_internal(array, xstart, xstop, xstep, ystart, ystop, ystep); if (!tmparray) { return -1; } retval = _pxarray_ass_slice(tmparray, 0, (Py_ssize_t)tmparray->dim0, value); Py_DECREF(tmparray); return retval; } else if (op == Py_Ellipsis) { /* A slice */ PyPixelArray *tmparray = (PyPixelArray *) _pxarray_subscript_internal(array, 0, array->dim0, 1, 0, array->dim1, 1); int retval; if (!tmparray) { return -1; } retval = _pxarray_ass_slice(tmparray, 0, (Py_ssize_t)tmparray->dim0, value); Py_DECREF(tmparray); return retval; } else if (PySlice_Check(op)) { /* A slice */ PyPixelArray *tmparray; Py_ssize_t slicelen; Py_ssize_t step; Py_ssize_t start; Py_ssize_t stop; int retval; if (Slice_GET_INDICES_EX(op, array->dim0, &start, &stop, &step, &slicelen)) { return -1; } if (slicelen < 0) { PyErr_SetString(PyExc_IndexError, "Unable to handle negative slice"); return -1; } if (slicelen == 0) { return 0; } tmparray = (PyPixelArray *)_array_slice_internal(array, start, stop, step); if (!tmparray) { return -1; } retval = _pxarray_ass_slice(tmparray, 0, (Py_ssize_t)tmparray->dim0, value); Py_DECREF(tmparray); return retval; } else if (PyIndex_Check(op) || PyInt_Check(op) || PyLong_Check(op)) { Py_ssize_t i; #if PY_VERSION_HEX >= 0x02050000 PyObject *val = PyNumber_Index(op); if (!val) { return -1; } /* A simple index. */ i = PyNumber_AsSsize_t(val, PyExc_IndexError); #else i = PyInt_Check(op) ? PyInt_AsLong (op) : PyLong_AsLong (op); #endif if (i == -1 && PyErr_Occurred()) { return -1; } return _pxarray_ass_item(array, i, value); } PyErr_SetString(PyExc_TypeError, "index must be an integer, sequence or slice"); return -1; } /**** C API interfaces ****/ static PyObject* PyPixelArray_New(PyObject *surfobj) { SDL_Surface *surf; Py_ssize_t dim0; Py_ssize_t dim1; Py_ssize_t stride0; Py_ssize_t stride1; Uint8 *pixels; if (!PySurface_Check(surfobj)) { return RAISE(PyExc_TypeError, "argument is no a Surface"); } surf = PySurface_AsSurface(surfobj); dim0 = (Py_ssize_t)surf->w; dim1 = (Py_ssize_t)surf->h; stride0 = (Py_ssize_t)surf->format->BytesPerPixel; stride1 = (Py_ssize_t)surf->pitch; pixels = surf->pixels; if (stride0 < 1 || stride0 > 4) { return RAISE(PyExc_ValueError, "unsupported bit depth for reference array"); } return (PyObject *)_pxarray_new_internal(&PyPixelArray_Type, surfobj, 0, pixels, dim0, dim1, stride0, stride1); } MODINIT_DEFINE(pixelarray) { PyObject *module; PyObject *apiobj; static void* c_api[PYGAMEAPI_PIXELARRAY_NUMSLOTS]; #if PY3 static struct PyModuleDef _module = { PyModuleDef_HEAD_INIT, "pixelarray", NULL, -1, NULL, NULL, NULL, NULL, NULL }; #endif /* imported needed apis; Do this first so if there is an error the module is not loaded. */ import_pygame_base(); if (PyErr_Occurred()) { MODINIT_ERROR; } import_pygame_color(); if (PyErr_Occurred()) { MODINIT_ERROR; } import_pygame_surface(); if (PyErr_Occurred()) { MODINIT_ERROR; } /* type preparation */ if (PyType_Ready(&PyPixelArray_Type)) { MODINIT_ERROR; } /* create the module */ #if PY3 module = PyModule_Create(&_module); #else module = Py_InitModule3(MODPREFIX "pixelarray", 0, 0); #endif if (!module) { MODINIT_ERROR; } Py_INCREF(&PyPixelArray_Type); if (PyModule_AddObject(module, "PixelArray", (PyObject *)&PyPixelArray_Type)) { Py_DECREF((PyObject *)&PyPixelArray_Type); DECREF_MOD(module); MODINIT_ERROR; } PyPixelArray_Type.tp_getattro = PyObject_GenericGetAttr; c_api[0] = &PyPixelArray_Type; c_api[1] = PyPixelArray_New; apiobj = encapsulate_api (c_api, "pixelarray"); if (apiobj == NULL) { DECREF_MOD(module); MODINIT_ERROR; } if (PyModule_AddObject(module, PYGAMEAPI_LOCAL_ENTRY, apiobj)) { Py_DECREF(apiobj); DECREF_MOD(module); MODINIT_ERROR; } MODINIT_RETURN(module); }
