Commits

Lenard Lindstrom committed 2799158

upgrade numpy handling to Python 3.x

  • Participants
  • Parent commits 9a99a51

Comments (0)

Files changed (5)

examples/arraydemo.py

 
     if surfarray.get_arraytype() == 'numpy':
         import numpy as N
-        from numpy import int32
+        from numpy import int32, uint8, uint
     else:
         import Numeric as N
-        from Numeric import Int32 as int32
+        from Numeric import Int32 as int32, UInt8 as uint8, UInt as uint
 
     pygame.init()
     print ('Using %s' % surfarray.get_arraytype().capitalize())
 
 
     #soften
-    soften = N.array(rgbarray)*1
-    soften[1:,:]  += rgbarray[:-1,:]*8
-    soften[:-1,:] += rgbarray[1:,:]*8
-    soften[:,1:]  += rgbarray[:,:-1]*8
-    soften[:,:-1] += rgbarray[:,1:]*8
-    soften /= 33
+    #having factor as an array forces integer upgrade during multiplication
+    #of rgbarray, even for numpy.
+    factor = N.array((8,), int32)
+    soften = N.array(rgbarray, int32)
+    soften[1:,:]  += rgbarray[:-1,:] * factor
+    soften[:-1,:] += rgbarray[1:,:] * factor
+    soften[:,1:]  += rgbarray[:,:-1] * factor
+    soften[:,:-1] += rgbarray[:,1:] * factor
+    soften //= 33
     surfdemo_show(soften, 'soften')
 
 
     dest = N.zeros(rgbarray.shape)
     dest[:] = 20, 50, 100
     diff = (dest - src) * 0.50
-    if surfarray.get_arraytype() == 'numpy':
-        xfade = src + diff.astype(N.uint)
-    else:
-        xfade = src + diff.astype(N.Int)
+    xfade = src + diff.astype(uint)
     surfdemo_show(xfade, 'xfade')
 
 

lib/_numpysurfarray.py

 """
 
 import pygame
+from pygame.compat import bytes_
+from pygame._arraysurfarray import blit_array
 import numpy
-import re
+
 
 def array2d (surface):
     """pygame.numpyarray.array2d (Surface): return array
     if bpp <= 0 or bpp > 4:
         raise ValueError("unsupported bit depth for 2D array")
 
+    size = surface.get_size ()
+    width, height = size
+    
     # Taken from Alex Holkner's pygame-ctypes package. Thanks a lot.
-    data = surface.get_buffer ().raw
-        
-    # Remove extra pitch from each row.
-    width = surface.get_width ()
-    pitchdiff = surface.get_pitch () - width * bpp
-    if pitchdiff > 0:
-        pattern = re.compile ('(%s)%s' % ('.' * width * bpp, '.' * pitchdiff),
-                              flags=re.DOTALL)
-        data = ''.join (pattern.findall (data))
+    data = numpy.frombuffer (surface.get_buffer (), numpy.uint8)
+    pitch = surface.get_pitch ()
+    row_size = width * bpp
+    if pitch != row_size:
+        data.shape = (height, pitch)
+        data = data[:, 0:row_size]
 
+    dtype = (None, numpy.uint8, numpy.uint16, numpy.int32, numpy.int32)[bpp]
+    array = numpy.zeros (size, dtype, 'F')
+    array_data = numpy.frombuffer (array, numpy.uint8)
     if bpp == 3:
-        # Pad each triplet of bytes with another zero
-        pattern = re.compile ('...', flags=re.DOTALL)
-        data = '\0'.join (pattern.findall (data))
-        if pygame.get_sdl_byteorder () == pygame.LIL_ENDIAN:
-            data += '\0'
-        else:
-            data = '\0' + data
-        bpp = 4
-
-    typecode = (numpy.uint8, numpy.uint16, None, numpy.int32)[bpp - 1]
-    array = numpy.fromstring (data, typecode)
-    array.shape = (surface.get_height (), width)
-    array = numpy.transpose (array)
+        data.shape = (height, width, 3)
+        array_data.shape = (height, width, 4)
+        array_data[:,:,:3] = data[...]
+    else:
+        data.shape = (height, row_size)
+        array_data.shape = (height, row_size)
+        array_data[...] =  data[...]
     return array
     
-
 def pixels2d (surface):
     """pygame.numpyarray.pixels2d (Surface): return array
 
     surface = pygame.Surface ((shape[0], shape[1]), 0, bpp, (r, g, b, 0))
     blit_array (surface, array)
     return surface
-
-def blit_array (surface, array):
-    """pygame.numpyarray.blit_array (Surface, array): return None
-
-    blit directly from a array values
-
-    Directly copy values from an array into a Surface. This is faster
-    than converting the array into a Surface and blitting. The array
-    must be the same dimensions as the Surface and will completely
-    replace all pixel values.
-
-    This function will temporarily lock the Surface as the new values
-    are copied.
-    """
-    bpp = surface.get_bytesize ()
-    if bpp <= 0 or bpp > 4:
-        raise ValueError("unsupported bit depth for surface")
-    
-    shape = array.shape
-    width = surface.get_width ()
-
-    typecode = (numpy.uint8, numpy.uint16, None, numpy.uint32)[bpp - 1]
-    array = array.astype (typecode)
-
-    # Taken from from Alex Holkner's pygame-ctypes package. Thanks a
-    # lot.
-    if len(shape) == 3 and shape[2] == 3:
-        array = numpy.transpose (array, (1, 0, 2))
-        shifts = surface.get_shifts ()
-        losses = surface.get_losses ()
-        array = (array[:,:,::3] >> losses[0] << shifts[0]) | \
-                (array[:,:,1::3] >> losses[1] << shifts[1]) | \
-                (array[:,:,2::3] >> losses[2] << shifts[2])
-    elif len (shape) == 2:
-        array = numpy.transpose (array)
-    else:
-        raise ValueError("must be a valid 2d or 3d array")
-
-    if width != shape[0] or surface.get_height () != shape[1]:
-        raise ValueError("array must match the surface dimensions")
-
-    itemsize = array.itemsize
-    data = array.tostring ()
-
-    if itemsize > bpp:
-        # Trim bytes from each element, keep least significant byte(s)
-        pattern = '%s(%s)' % ('.' * (itemsize - bpp), '.' * bpp)
-        if pygame.get_sdl_byteorder () == pygame.LIL_ENDIAN:
-            pattern = '(%s)%s' % ('.' * bpp, '.' * (itemsize - bpp))
-        data = ''.join (re.compile (pattern, flags=re.DOTALL).findall (data))
-    elif itemsize < bpp:
-        # Add pad bytes to each element, at most significant end
-        pad = '\0' * (bpp - itemsize)
-        pixels = re.compile ('.' * itemsize, flags=re.DOTALL).findall (data)
-        data = pad.join (pixels)
-        if pygame.get_sdl_byteorder () == pygame.LIL_ENDIAN:
-            data = data + pad
-        else:
-            data = pad + data
-
-    # Add zeros pad for pitch correction
-    pitchdiff = surface.get_pitch () - width * bpp
-    if pitchdiff > 0:
-        pad = '\0' * pitchdiff
-        rows = re.compile ('.' * width * bpp, flags=re.DOTALL).findall (data)
-        data = pad.join (rows) + pad
-
-    surface.get_buffer ().write (data, 0)
     
 def map_array (surface, array):
     """pygame.numpyarray.map_array (Surface, array3d): return array2d
 if not __hasnumpy and not __hasnumeric:
     raise ImportError("no module named numpy or Numeric found")
 
-from _arraysurfarray import blit_array
+from pygame._arraysurfarray import blit_array
 
 def array2d (surface):
     """pygame.surfarray.array2d (Surface): return array
         return numpysf.make_surface (array)
     raise NotImplementedError("surface arrays are not supported")
 
-##def blit_array (surface, array):
-##    """pygame.surfarray.blit_array (Surface, array): return None
-##
-##    Blit directly from a array values.
-##
-##    Directly copy values from an array into a Surface. This is faster
-##    than converting the array into a Surface and blitting. The array
-##    must be the same dimensions as the Surface and will completely
-##    replace all pixel values.
-##
-##    This function will temporarily lock the Surface as the new values
-##    are copied.
-##    """
-##    if __arraytype == "numeric":
-##        return numericsf.blit_array (surface, array)
-##    elif __arraytype == "numpy":
-##        return numpysf.blit_array (surface, array)
-##    raise NotImplementedError("surface arrays are not supported")
-
 def map_array (surface, array):
     """pygame.surfarray.map_array (Surface, array3d): return array2d
 

src/_arraysurfarray.c

 
 static int
 _get_array_interface(PyObject *obj,
-		     PyObject **cobj_p,
-		     PyArrayInterface **inter_p)
+                     PyObject **cobj_p,
+                     PyArrayInterface **inter_p)
 {
-    if (!(*cobj_p = PyObject_GetAttrString(obj, "__array_struct__"))) {
-	if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
-		PyErr_Clear();
-		PyErr_SetString(PyExc_ValueError,
-				"no C-struct array interface");
-	    }
-	return 0;
+    PyObject *cobj = PyObject_GetAttrString(obj, "__array_struct__");
+    PyArrayInterface *inter = NULL;
+
+    if (cobj == NULL) {
+        if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
+                PyErr_Clear();
+                PyErr_SetString(PyExc_ValueError,
+                                "no C-struct array interface");
+        }
+        return 0;
     }
 
-    if (!PyCObject_Check(*cobj_p) ||  /* conditional 'or's */
-	!(*inter_p = PyCObject_AsVoidPtr(*cobj_p)) ||
-	(*inter_p)->two != 2) {
-	Py_DECREF(*cobj_p);
-	PyErr_SetString(PyExc_ValueError, "invalid array interface");
-	return 0;
+#if defined(PyCObject_Check)
+    if (PyCObject_Check(cobj)) {
+        inter = (PyArrayInterface *)PyCObject_AsVoidPtr(cobj);
     }
+#endif
+#if defined(PyCapsule_CheckExact)
+    if (PyCapsule_IsValid(cobj, NULL)) {
+        inter = (PyArrayInterface *)PyCapsule_GetPointer(cobj, NULL);
+    }
+#endif
+    if (inter == NULL ||   /* conditional or */
+        inter->two != 2  ) {
+        Py_DECREF(cobj);
+        PyErr_SetString(PyExc_ValueError, "invalid array interface");
+        return 0;
+    }
+
+    *cobj_p = cobj;
+    *inter_p = inter;
     return 1;
 }
 
 /*macros used to blit arrays*/
-#define COPYMACRO_2D(DST, SRC)                                           \
-    for (loopy = 0; loopy < sizey; ++loopy)                              \
-    {                                                                    \
-        DST* imgrow = (DST*)(((char*)surf->pixels)+loopy*surf->pitch);   \
-        Uint8* datarow = (Uint8*)array_data + stridey * loopy;           \
-        for (loopx = 0; loopx < sizex; ++loopx)                          \
-            *(imgrow + loopx) = (DST)*(SRC*)(datarow + stridex * loopx); \
+#define COPYMACRO_2D(DST, SRC)                                            \
+    for (loopy = 0; loopy < sizey; ++loopy)                               \
+    {                                                                     \
+        DST* imgrow = (DST*)(((char*)surf->pixels)+loopy*surf->pitch);    \
+        Uint8* datarow = (Uint8*)array_data + stridey * loopy;            \
+        for (loopx = 0; loopx < sizex; ++loopx)                           \
+            *(imgrow + loopx) = (DST)*(SRC*)(datarow + stridex * loopx);  \
     }
 
 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
-#define COPYMACRO_2D_24_PIXEL(pix, data, SRC)    			\
-    *pix++ = *data;					                \
-    *pix++ = *(data + 1);					        \
+#define COPYMACRO_2D_24_PIXEL(pix, data, SRC)                             \
+    *pix++ = *data;                                                       \
+    *pix++ = *(data + 1);                                                 \
     *pix++ = *(data + 2);
 #else
-#define COPYMACRO_2D_24_PIXEL(pix, data, SRC)    			\
-    *pix++ = *(data + sizeof (SRC) - 1);				\
-    *pix++ = *(data + sizeof (SRC) - 2);				\
+#define COPYMACRO_2D_24_PIXEL(pix, data, SRC)                             \
+    *pix++ = *(data + sizeof (SRC) - 1);                                  \
+    *pix++ = *(data + sizeof (SRC) - 2);                                  \
     *pix++ = *(data + sizeof (SRC) - 3);
 #endif
 
-#define COPYMACRO_2D_24(SRC)                                            \
-    for (loopy = 0; loopy < sizey; ++loopy)                             \
-    {                                                                   \
-        Uint8 *pix = ((Uint8 *)surf->pixels) + loopy * surf->pitch;     \
-        Uint8 *data = (Uint8 *)array_data + stridey * loopy;            \
-        Uint8 *end = pix + 3 * sizex;                                   \
-        while (pix != end) {                                            \
-            COPYMACRO_2D_24_PIXEL(pix, data, SRC)			\
-            data += stridex;                                            \
-        }                                                               \
+#define COPYMACRO_2D_24(SRC)                                              \
+    for (loopy = 0; loopy < sizey; ++loopy)                               \
+    {                                                                     \
+        Uint8 *pix = ((Uint8 *)surf->pixels) + loopy * surf->pitch;       \
+        Uint8 *data = (Uint8 *)array_data + stridey * loopy;              \
+        Uint8 *end = pix + 3 * sizex;                                     \
+        while (pix != end) {                                              \
+            COPYMACRO_2D_24_PIXEL(pix, data, SRC)                         \
+            data += stridex;                                              \
+        }                                                                 \
     }
 
 #define COPYMACRO_3D(DST, SRC)                                            \
     {                                                                   \
         Uint8 *pix = ((Uint8*)surf->pixels) + surf->pitch * loopy;      \
         Uint8 *data = (Uint8*)array_data + stridey * loopy;             \
-	Uint8 *end = pix + 3 * sizex;                                   \
+        Uint8 *end = pix + 3 * sizex;                                   \
         while (pix != end) {                                            \
             *pix++ = (Uint8)*(SRC*)(data + stridez_0);                  \
             *pix++ = (Uint8)*(SRC*)(data + stridez_1);                  \
     }
 
 static PyObject*
-blit_array(PyObject* self, PyObject* arg)
+blit_array(PyObject *self, PyObject *arg)
 {
     PyObject *surfobj, *arrayobj;
     PyObject *cobj;
 
     switch (inter->typekind) {
     case 'i':  /* integer */
-	break;
+        break;
     case 'u':  /* unsigned integer */ 
-	break;
+        break;
     case 'S':  /* fixed length character field */
-	break;
+        break;
     case 'V':  /* structured element: record */
-	break;
+        break;
     default:
-	Py_DECREF(cobj);
-	PyErr_Format(PyExc_ValueError, "unsupported array type '%c'",
-		     inter->typekind);
-	return NULL;
+        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)))
         Py_DECREF(cobj);
         return RAISE(PyExc_ValueError, "array must match surface dimensions");
     }
-    if (!PySurface_LockBy(surfobj, (PyObject *) arrayobj)) {
+    if (!PySurface_LockBy(surfobj, arrayobj)) {
         Py_DECREF(cobj);
         return NULL;
     }
                 break;
             default:
                 Py_DECREF(cobj);
-                if (!PySurface_UnlockBy(surfobj, (PyObject *) arrayobj)) {
+                if (!PySurface_UnlockBy(surfobj, arrayobj)) {
                     return NULL;
                 }
                 return RAISE(PyExc_ValueError,
         }
         else {
             Py_DECREF(cobj);
-            if (!PySurface_UnlockBy(surfobj, (PyObject *) arrayobj)) {
+            if (!PySurface_UnlockBy(surfobj, arrayobj)) {
                 return NULL;
             }
             return RAISE(PyExc_ValueError,
                 break;
             default:
                 Py_DECREF(cobj);
-                if (!PySurface_UnlockBy(surfobj, (PyObject *) arrayobj)) {
+                if (!PySurface_UnlockBy(surfobj, arrayobj)) {
                     return NULL;
                 }
                 return RAISE(PyExc_ValueError,
             }
         }
         else {
-	    Uint16 alpha = 0;
-	    if (format->Amask) {
-		alpha = 255 >> format->Aloss << format->Ashift;
-	    }
+            Uint16 alpha = 0;
+            if (format->Amask) {
+                alpha = 255 >> format->Aloss << format->Ashift;
+            }
             switch (inter->itemsize) {
             case sizeof (Uint8):
                 COPYMACRO_3D(Uint16, Uint8);
                 break;
             default:
                 Py_DECREF(cobj);
-                if (!PySurface_UnlockBy(surfobj, (PyObject *) arrayobj)) {
+                if (!PySurface_UnlockBy(surfobj, arrayobj)) {
                     return NULL;
                 }
                 return RAISE(PyExc_ValueError,
     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):
                 break;
             default:
                 Py_DECREF(cobj);
-                if (!PySurface_UnlockBy(surfobj, (PyObject *) arrayobj)) {
+                if (!PySurface_UnlockBy(surfobj, arrayobj)) {
                     return NULL;
                 }
                 return RAISE(PyExc_ValueError,
         }
         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  :
+            size_t stridez_0 = (Rshift ==  0 ? 0        :
+                                Gshift ==  0 ? stridez  :
                                                stridez2   );
-	    size_t stridez_2 = (Rshift == 16 ? 0        :
+            size_t stridez_1 = (Rshift ==  8 ? 0        :
+                                Gshift ==  8 ? stridez  :
+                                               stridez2   );
+            size_t stridez_2 = (Rshift == 16 ? 0        :
                                 Gshift == 16 ? stridez  :
-				               stridez2   );
+                                               stridez2   );
 #else
-	    size_t stridez_2 = (Rshift ==  0 ? 0        :
-				Gshift ==  0 ? stridez  :
-				               stridez2   );
-	    size_t stridez_1 = (Rshift ==  8 ? 0        :
-				Gshift ==  8 ? stridez  :
+            size_t stridez_2 = (Rshift ==  0 ? 0        :
+                                Gshift ==  0 ? stridez  :
                                                stridez2   );
-	    size_t stridez_0 = (Rshift == 16 ? 0        :
+            size_t stridez_1 = (Rshift ==  8 ? 0        :
+                                Gshift ==  8 ? stridez  :
+                                               stridez2   );
+            size_t stridez_0 = (Rshift == 16 ? 0        :
                                 Gshift == 16 ? stridez  :
-				               stridez2   );
+                                               stridez2   );
 #endif
             switch (inter->itemsize) {
             case sizeof (Uint8):
                 break;
             default:
                 Py_DECREF(cobj);
-                if (!PySurface_UnlockBy(surfobj, (PyObject *) arrayobj)) {
+                if (!PySurface_UnlockBy(surfobj, arrayobj)) {
                     return NULL;
                 }
                 return RAISE(PyExc_ValueError,
                 break;
             default:
                 Py_DECREF(cobj);
-                if (!PySurface_UnlockBy(surfobj, (PyObject *) arrayobj)) {
+                if (!PySurface_UnlockBy(surfobj, arrayobj)) {
                     return NULL;
                 }
                 return RAISE(PyExc_ValueError,
             }
         }
         else {
-	    Uint32 alpha = 0;
-	    if (format->Amask) {
-		alpha = 255 >> format->Aloss << format->Ashift;
-	    }
+            Uint32 alpha = 0;
+            if (format->Amask) {
+                alpha = 255 >> format->Aloss << format->Ashift;
+            }
             switch (inter->itemsize) {
             case sizeof (Uint8):
                 COPYMACRO_3D(Uint32, Uint8);
                 break;
             default:
                 Py_DECREF(cobj);
-                if (!PySurface_UnlockBy(surfobj, (PyObject *) arrayobj)) {
+                if (!PySurface_UnlockBy(surfobj, arrayobj)) {
                     return NULL;
                 }
                 return RAISE(PyExc_ValueError,
         break;
     default:
         Py_DECREF(cobj);
-        if (!PySurface_UnlockBy(surfobj, (PyObject *) arrayobj)) {
+        if (!PySurface_UnlockBy(surfobj, arrayobj)) {
             return NULL;
         }
         return RAISE(PyExc_RuntimeError, "unsupported bit depth for image");
     }
     
     Py_DECREF(cobj);
-    if (!PySurface_UnlockBy(surfobj, (PyObject *) arrayobj)) {
+    if (!PySurface_UnlockBy(surfobj, arrayobj)) {
         return NULL;
     }
     Py_RETURN_NONE;
     */
     import_pygame_base();
     if (PyErr_Occurred ()) {
-	MODINIT_ERROR;
+        MODINIT_ERROR;
     }
     import_pygame_surface();
     if (PyErr_Occurred ()) {
-	MODINIT_ERROR;
+        MODINIT_ERROR;
     }
 
 #if PY3

test/sndarray_test.py

 else:
     from test.test_utils import test_not_implemented, unittest
 import pygame
+from pygame.compat import as_bytes
 
 arraytype = ""
 try:
         if not arraytype:
             self.fail("no array package installed")
 
+        null_byte = as_bytes('\x00')
         def check_sample(size, channels, test_data):
             try:
                 pygame.mixer.init(22050, size, channels)
             try:
                 __, sz, __ = pygame.mixer.get_init()
                 if sz == size:
-                    zeroed = '\0' * ((abs(size) // 8) *
-                                     len(test_data) *
-                                     channels)
-                    snd = pygame.mixer.Sound(buffer(zeroed))
+                    zeroed = null_byte * ((abs(size) // 8) *
+                                          len(test_data) *
+                                          channels)
+                    snd = pygame.mixer.Sound(buffer=zeroed)
                     samples = pygame.sndarray.samples(snd)
                     self._assert_compatible(samples, size)
-                    print ('X %s' % (samples.shape,))
-                    print ('Y %s' % (test_data,))
+                    ##print ('X %s' % (samples.shape,))
+                    ##print ('Y %s' % (test_data,))
                     samples[...] = test_data
                     arr = pygame.sndarray.array(snd)
                     self.failUnless(alltrue(samples == arr),