static PyObject* blit_array(PyObject* self, PyObject* arg) { PyObject *surfobj, *arrayobj; PyObject *cobj; PyArrayInterface *inter; char *array_data; SDL_Surface* surf; SDL_PixelFormat* format; int loopx, loopy; int stridex, stridey, stridez=0, stridez2=0, sizex, sizey; int Rloss, Gloss, Bloss, Rshift, Gshift, Bshift; if (!PyArg_ParseTuple(arg, "O!O", &PySurface_Type, &surfobj, &arrayobj)) { return NULL; } surf = PySurface_AsSurface(surfobj); format = surf->format; if (!_get_array_interface(arrayobj, &cobj, &inter)) { return 0; } switch (inter->typekind) { case 'i': /* integer */ break; case 'u': /* unsigned integer */ break; case 'S': /* fixed length character field */ break; case 'V': /* structured element: record */ break; default: Py_DECREF(cobj); PyErr_Format(PyExc_ValueError, "unsupported array type '%c'", inter->typekind); return NULL; } if (!(inter->nd == 2 || (inter->nd == 3 && inter->shape[2] == 3))) return RAISE(PyExc_ValueError, "must be a valid 2d or 3d array\n"); if (surf->format->BytesPerPixel <= 0 || surf->format->BytesPerPixel > 4) return RAISE(PyExc_ValueError, "unsupport bit depth for surface"); stridex = inter->strides[0]; stridey = inter->strides[1]; if (inter->nd == 3) { stridez = inter->strides[2]; stridez2 = stridez*2; } sizex = inter->shape[0]; sizey = inter->shape[1]; Rloss = format->Rloss; Gloss = format->Gloss; Bloss = format->Bloss; Rshift = format->Rshift; Gshift = format->Gshift; Bshift = format->Bshift; if (sizex != surf->w || sizey != surf->h) { Py_DECREF(cobj); return RAISE(PyExc_ValueError, "array must match surface dimensions"); } if (!PySurface_LockBy(surfobj, (PyObject *) arrayobj)) { Py_DECREF(cobj); return NULL; } array_data = (char *)inter->data; switch (surf->format->BytesPerPixel) { case 1: if (inter->nd == 2) { switch (inter->itemsize) { case sizeof (Uint8): COPYMACRO_2D(Uint8, Uint8); break; case sizeof (Uint16): COPYMACRO_2D(Uint8, Uint16); break; case sizeof (Uint32): COPYMACRO_2D(Uint8, Uint32); break; case sizeof (Uint64): COPYMACRO_2D(Uint8, Uint64); break; default: Py_DECREF(cobj); if (!PySurface_UnlockBy(surfobj, (PyObject *) arrayobj)) { return NULL; } return RAISE(PyExc_ValueError, "unsupported datatype for array\n"); } } else { Py_DECREF(cobj); if (!PySurface_UnlockBy(surfobj, (PyObject *) arrayobj)) { return NULL; } return RAISE(PyExc_ValueError, "unsupported datatype for array\n"); } break; case 2: if (inter->nd == 2) { switch (inter->itemsize) { case sizeof (Uint16): COPYMACRO_2D(Uint16, Uint16); break; case sizeof (Uint32): COPYMACRO_2D(Uint16, Uint32); break; case sizeof (Uint64): COPYMACRO_2D(Uint16, Uint64); break; default: Py_DECREF(cobj); if (!PySurface_UnlockBy(surfobj, (PyObject *) arrayobj)) { return NULL; } return RAISE(PyExc_ValueError, "unsupported datatype for array\n"); } } else { Uint16 alpha = 0; if (format->Amask) { alpha = 255 >> format->Aloss << format->Ashift; } switch (inter->itemsize) { case sizeof (Uint8): COPYMACRO_3D(Uint16, Uint8); break; case sizeof (Uint16): COPYMACRO_3D(Uint16, Uint16); break; case sizeof (Uint32): COPYMACRO_3D(Uint16, Uint32); break; case sizeof (Uint64): COPYMACRO_3D(Uint16, Uint64); break; default: Py_DECREF(cobj); if (!PySurface_UnlockBy(surfobj, (PyObject *) arrayobj)) { return NULL; } return RAISE(PyExc_ValueError, "unsupported datatype for array\n"); } } break; case 3: /* Assumption: The rgb components of a 24 bit pixel are in separate bytes. */ if (inter->nd == 2) { switch (inter->itemsize) { case sizeof (Uint32): COPYMACRO_2D_24(Uint32); break; case sizeof (Uint64): COPYMACRO_2D_24(Uint64); break; default: Py_DECREF(cobj); if (!PySurface_UnlockBy(surfobj, (PyObject *) arrayobj)) { return NULL; } return RAISE(PyExc_ValueError, "unsupported datatype for array\n"); } } else { #if SDL_BYTEORDER == SDL_LIL_ENDIAN size_t stridez_0 = (Rshift == 0 ? 0 : Gshift == 0 ? stridez : stridez2 ); size_t stridez_1 = (Rshift == 8 ? 0 : Gshift == 8 ? stridez : stridez2 ); size_t stridez_2 = (Rshift == 16 ? 0 : Gshift == 16 ? stridez : stridez2 ); #else size_t stridez_2 = (Rshift == 0 ? 0 : Gshift == 0 ? stridez : stridez2 ); size_t stridez_1 = (Rshift == 8 ? 0 : Gshift == 8 ? stridez : stridez2 ); size_t stridez_0 = (Rshift == 16 ? 0 : Gshift == 16 ? stridez : stridez2 ); #endif switch (inter->itemsize) { case sizeof (Uint8): COPYMACRO_3D_24(Uint8); break; case sizeof (Uint16): COPYMACRO_3D_24(Uint16); break; case sizeof (Uint32): COPYMACRO_3D_24(Uint32); break; case sizeof (Uint64): COPYMACRO_3D_24(Uint64); break; default: Py_DECREF(cobj); if (!PySurface_UnlockBy(surfobj, (PyObject *) arrayobj)) { return NULL; } return RAISE(PyExc_ValueError, "unsupported datatype for array\n"); } } break; case 4: if (inter->nd == 2) { switch (inter->itemsize) { case sizeof (Uint32): COPYMACRO_2D(Uint32, Uint32); break; case sizeof (Uint64): COPYMACRO_2D(Uint32, Uint64); break; default: Py_DECREF(cobj); if (!PySurface_UnlockBy(surfobj, (PyObject *) arrayobj)) { return NULL; } return RAISE(PyExc_ValueError, "unsupported datatype for array\n"); } } else { Uint32 alpha = 0; if (format->Amask) { alpha = 255 >> format->Aloss << format->Ashift; } switch (inter->itemsize) { case sizeof (Uint8): COPYMACRO_3D(Uint32, Uint8); break; case sizeof (Uint16): COPYMACRO_3D(Uint32, Uint16); break; case sizeof (Uint32): COPYMACRO_3D(Uint32, Uint32); break; case sizeof (Uint64): COPYMACRO_3D(Uint32, Uint64); break; default: Py_DECREF(cobj); if (!PySurface_UnlockBy(surfobj, (PyObject *) arrayobj)) { return NULL; } return RAISE(PyExc_ValueError, "unsupported datatype for array\n"); } }
static PyObject* array_to_surface(PyObject *self, PyObject *arg) { PyObject *surfobj, *arrayobj; Pg_buffer pg_view; Py_buffer *view_p = (Py_buffer *)&pg_view; char *array_data; SDL_Surface* surf; SDL_PixelFormat* format; int loopx, loopy; int stridex, stridey, stridez=0, stridez2=0, sizex, sizey; int Rloss, Gloss, Bloss, Rshift, Gshift, Bshift; if (!PyArg_ParseTuple(arg, "O!O", &PySurface_Type, &surfobj, &arrayobj)) { return NULL; } surf = PySurface_AsSurface(surfobj); format = surf->format; if (PgObject_GetBuffer(arrayobj, &pg_view, PyBUF_RECORDS_RO)) { return 0; } if (_validate_view_format(view_p->format)) { return 0; } if (!(view_p->ndim == 2 || (view_p->ndim == 3 && view_p->shape[2] == 3))) { return RAISE(PyExc_ValueError, "must be a valid 2d or 3d array\n"); } if (surf->format->BytesPerPixel <= 0 || surf->format->BytesPerPixel > 4) return RAISE(PyExc_ValueError, "unsupport bit depth for surface"); stridex = view_p->strides[0]; stridey = view_p->strides[1]; if (view_p->ndim == 3) { stridez = view_p->strides[2]; stridez2 = stridez*2; } else { stridez = 1; stridez2 = 2; } sizex = view_p->shape[0]; sizey = view_p->shape[1]; Rloss = format->Rloss; Gloss = format->Gloss; Bloss = format->Bloss; Rshift = format->Rshift; Gshift = format->Gshift; Bshift = format->Bshift; /* Do any required broadcasting. */ if (sizex == 1) { sizex = surf->w; stridex = 0; } if (sizey == 1) { sizey = surf->h; stridey = 0; } if (sizex != surf->w || sizey != surf->h) { PgBuffer_Release(&pg_view); return RAISE(PyExc_ValueError, "array must match surface dimensions"); } if (!PySurface_LockBy(surfobj, arrayobj)) { PgBuffer_Release(&pg_view); return NULL; } array_data = (char *)view_p->buf; switch (surf->format->BytesPerPixel) { case 1: if (view_p->ndim == 2) { switch (view_p->itemsize) { case sizeof (Uint8): COPYMACRO_2D(Uint8, Uint8); break; case sizeof (Uint16): COPYMACRO_2D(Uint8, Uint16); break; case sizeof (Uint32): COPYMACRO_2D(Uint8, Uint32); break; case sizeof (Uint64): COPYMACRO_2D(Uint8, Uint64); break; default: PgBuffer_Release(&pg_view); if (!PySurface_UnlockBy(surfobj, arrayobj)) { return NULL; } return RAISE(PyExc_ValueError, "unsupported datatype for array\n"); } } else { PgBuffer_Release(&pg_view); if (!PySurface_UnlockBy(surfobj, arrayobj)) { return NULL; } return RAISE(PyExc_ValueError, "unsupported datatype for array\n"); } break; case 2: if (view_p->ndim == 2) { switch (view_p->itemsize) { case sizeof (Uint16): COPYMACRO_2D(Uint16, Uint16); break; case sizeof (Uint32): COPYMACRO_2D(Uint16, Uint32); break; case sizeof (Uint64): COPYMACRO_2D(Uint16, Uint64); break; default: PgBuffer_Release(&pg_view); if (!PySurface_UnlockBy(surfobj, arrayobj)) { return NULL; } return RAISE(PyExc_ValueError, "unsupported datatype for array\n"); } } else { Uint16 alpha = 0; if (format->Amask) { alpha = 255 >> format->Aloss << format->Ashift; } switch (view_p->itemsize) { case sizeof (Uint8): COPYMACRO_3D(Uint16, Uint8); break; case sizeof (Uint16): COPYMACRO_3D(Uint16, Uint16); break; case sizeof (Uint32): COPYMACRO_3D(Uint16, Uint32); break; case sizeof (Uint64): COPYMACRO_3D(Uint16, Uint64); break; default: PgBuffer_Release(&pg_view); if (!PySurface_UnlockBy(surfobj, arrayobj)) { return NULL; } return RAISE(PyExc_ValueError, "unsupported datatype for array\n"); } } break; case 3: /* Assumption: The rgb components of a 24 bit pixel are in separate bytes. */ if (view_p->itemsize >= (view_p->ndim == 2 ? 3 : 1) && view_p->itemsize <= 9) { size_t stridez_0 = 0; size_t stridez_1 = 0; size_t stridez_2 = 0; #if SDL_BYTEORDER == SDL_LIL_ENDIAN if (view_p->ndim == 2) { stridez_1 = 1; stridez_2 = 2; } else { size_t offset = _is_swapped(view_p) ? view_p->itemsize - 1 : 0; stridez_0 = ((Rshift == 0 ? 0 : (Gshift == 0 ? stridez : stridez2)) + offset); stridez_1 = ((Rshift == 8 ? 0 : (Gshift == 8 ? stridez : stridez2)) + offset); stridez_2 = ((Rshift == 16 ? 0 : (Gshift == 16 ? stridez : stridez2)) + offset); } #else if (view_p->ndim == 2) { stridez_0 = view_p->itemsize - 3; stridez_1 = stridez_0 + 1; stridez_2 = stridez_1 + 1; } else { size_t offset = _is_swapped(view_p) ? 0 : view_p->itemsize - 1; stridez_2 = ((Rshift == 0 ? 0 : (Gshift == 0 ? stridez : stridez2)) + offset); stridez_1 = ((Rshift == 8 ? 0 : (Gshift == 8 ? stridez : stridez2)) + offset); stridez_0 = ((Rshift == 16 ? 0 : (Gshift == 16 ? stridez : stridez2)) + offset); } #endif for (loopy = 0; loopy < sizey; ++loopy) { Uint8 *pix = ((Uint8*)surf->pixels) + surf->pitch * loopy; Uint8 *data = (Uint8*)array_data + stridey * loopy; Uint8 *end = pix + 3 * sizex; while (pix != end) { *pix++ = *(data + stridez_0); *pix++ = *(data + stridez_1); *pix++ = *(data + stridez_2); data += stridex; } } } else { PgBuffer_Release(&pg_view); if (!PySurface_UnlockBy(surfobj, arrayobj)) { return NULL; } return RAISE(PyExc_ValueError, "unsupported datatype for array\n"); } break; case 4: if (view_p->ndim == 2) { switch (view_p->itemsize) { case sizeof (Uint32): COPYMACRO_2D(Uint32, Uint32); break; case sizeof (Uint64): COPYMACRO_2D(Uint32, Uint64); break; default: PgBuffer_Release(&pg_view); if (!PySurface_UnlockBy(surfobj, arrayobj)) { return NULL; } return RAISE(PyExc_ValueError, "unsupported datatype for array\n"); } } else { Uint32 alpha = 0; if (format->Amask) { alpha = 255 >> format->Aloss << format->Ashift; } switch (view_p->itemsize) { case sizeof (Uint8): COPYMACRO_3D(Uint32, Uint8); break; case sizeof (Uint16): COPYMACRO_3D(Uint32, Uint16); break; case sizeof (Uint32): COPYMACRO_3D(Uint32, Uint32); break; case sizeof (Uint64): COPYMACRO_3D(Uint32, Uint64); break; default: PgBuffer_Release(&pg_view); if (!PySurface_UnlockBy(surfobj, arrayobj)) { return NULL; } return RAISE(PyExc_ValueError, "unsupported datatype for array\n"); } }