Commits

Anonymous committed 404e3a0

Added PixelArray.extract() method.

Comments (0)

Files changed (8)

 #
 #
 Apr 4, 2008
-    Added PixelArray.replace() method to quickly replace a certain
-      color.
+    New PixelArray.replace() and PixelArray.extract() methods to quickly
+      replace or extract a certain color.
 
 Apr 3, 2008
     Added iter support to PixelArray.

docs/ref/index.html

 </ul>
 <li><a href="pixelarray.html#pygame.PixelArray">pygame.PixelArray</a> - <font size=-1>pygame Object for direct pixel access of surfaces</font></li>
 <ul>
+<li><a href="pixelarray.html#PixelArray.extract">PixelArray.extract</a> - <font size=-1>Extracts the passed color in the PixelArray.</font></li>
 <li><a href="pixelarray.html#PixelArray.make_surface">PixelArray.make_surface</a> - <font size=-1>Creates a new Surface from the current PixelArray.</font></li>
 <li><a href="pixelarray.html#PixelArray.replace">PixelArray.replace</a> - <font size=-1>Replaces the passed color in the PixelArray with another one.</font></li>
 <li><a href="pixelarray.html#PixelArray.surface">PixelArray.surface</a> - <font size=-1>Gets the Surface the PixelArray uses.</font></li>

docs/ref/pixelarray.html

   <tr><td><a href="pixelarray.html#PixelArray.surface">PixelArray.surface</a> - <font size=-1>Gets the Surface the PixelArray uses.</font></td><td>Gets the Surface the PixelArray uses.</td></tr>
   <tr><td><a href="pixelarray.html#PixelArray.make_surface">PixelArray.make_surface</a> - <font size=-1>Creates a new Surface from the current PixelArray.</font></td><td>Creates a new Surface from the current PixelArray.</td></tr>
   <tr><td><a href="pixelarray.html#PixelArray.replace">PixelArray.replace</a> - <font size=-1>Replaces the passed color in the PixelArray with another one.</font></td><td>Replaces the passed color in the PixelArray with another one.</td></tr>
+  <tr><td><a href="pixelarray.html#PixelArray.extract">PixelArray.extract</a> - <font size=-1>Extracts the passed color in the PixelArray.</font></td><td>Extracts the passed color in the PixelArray.</td></tr>
 </table></small></ul>
 <p>The PixelArray wraps up a Surface and provides a direct <tt>2D</tt> array access to its pixels using the surface its rows as first and its columns as second axis. It supports slicing, row and pixel manipluation, slicing and slice assignments while inplace operations such as addition, subtraction, multiplication, division and so forth are not allowed. </p>
 <p>While it is possible to assign both, integer color values and <tt>RGB(A)</tt> color tuples, the PixelArray will only use integers for the color representation. Thus, checking for certain colors has to be done using the <tt><a href="surface.html#Surface.map_rgb">Surface.map_rgb</a> - <font size=-1>convert a color into a mapped color value</font></tt> method of the surface, the PixelArray was created for. </p>
 <big><b>PixelArray.replace</big></b><br><ul>
   <i>Replaces the passed color in the PixelArray with another one.</i><br>
   <tt>PixelArray.replace (color, replacecolor): Return None</tt><br>
-<p>Replaces the pixels with the passed color in the PixelArray by changing them them to the passed replacement color. </p>
+<p>Replaces the pixels with the passed color in the PixelArray by changing them them to the passed replacement color. The replacement is done in place on the PixelArray. </p>
 <p>New in <tt>pygame.1.8.1</tt>. </p>
 <!--COMMENTS:PixelArray.replace--> &nbsp;<br> 
 <br></ul>
+
+
+<a name="PixelArray.extract">
+<big><b>PixelArray.extract</big></b><br><ul>
+  <i>Extracts the passed color in the PixelArray.</i><br>
+  <tt>PixelArray.extract (color): Return None</tt><br>
+<p>Extracts the passed color by changing all matching pixels to white, while non-matching pixels are changed to black. The extraction is done in place on the PixelArray. </p>
+<p>New in <tt>pygame.1.8.1</tt>. </p>
+<!--COMMENTS:PixelArray.extract--> &nbsp;<br> 
+<br></ul>
 <br></ul>
 
 </body></html>
 {
     { "replace", (PyCFunction) _replace_color, METH_VARARGS,
       DOC_PIXELARRAYREPLACE },
+    { "extract", (PyCFunction) _extract_color, METH_VARARGS,
+      DOC_PIXELARRAYEXTRACT },
     { "make_surface", (PyCFunction) _make_surface, METH_NOARGS,
       DOC_PIXELARRAYMAKESURFACE },
     { NULL, NULL, 0, NULL }

src/pixelarray.doc

 PixelArray.replace (color, replacecolor): Return None
 
 Replaces the pixels with the passed color in the PixelArray by changing
-them them to the passed replacement color.
+them them to the passed replacement color. The replacement is done
+in place on the PixelArray.
 
 New in pygame.1.8.1.
 <END>
+
+extract
+Extracts the passed color in the PixelArray.
+PixelArray.extract (color): Return None
+
+Extracts the passed color by changing all matching pixels to white,
+while non-matching pixels are changed to black. The extraction is
+done in place on the PixelArray.
+
+New in pygame.1.8.1.
 <END>
+<END>

src/pixelarray_methods.c

     }
     Py_RETURN_NONE;
 }
+
+
+static PyObject*
+_extract_color (PyPixelArray *array, PyObject *args)
+{
+    PyObject *excolor = NULL;
+    Uint32 color;
+    Uint32 white;
+    Uint32 black;
+    SDL_Surface *surface;
+
+    Uint32 x = 0;
+    Uint32 y = 0;
+    Uint32 posx = 0;
+    Uint32 posy = 0;
+    Sint32 absxstep;
+    Sint32 absystep;
+    Uint8 *pixels;
+
+    if (!PyArg_ParseTuple (args, "O", &excolor))
+        return NULL;
+
+    surface = PySurface_AsSurface (array->surface);
+    if (!_get_color_from_object (excolor, surface->format, &color))
+        return NULL;
+
+    black = SDL_MapRGBA (surface->format, 0, 0, 0, 255);
+    white = SDL_MapRGBA (surface->format, 255, 255, 255, 255);
+
+    surface = PySurface_AsSurface (array->surface);
+    pixels = surface->pixels;
+    absxstep = ABS (array->xstep);
+    absystep = ABS (array->ystep);
+    y = array->ystart;
+
+    switch (surface->format->BytesPerPixel)
+    {
+    case 1:
+    {
+        Uint8 *pixel;
+        while (posy < array->ylen)
+        {
+            x = array->xstart;
+            posx = 0;
+            while (posx < array->xlen)
+            {
+                pixel = ((Uint8 *) pixels + y * surface->pitch + x);
+                *pixel = (*pixel == color) ? (Uint8) white : (Uint8) black;
+                x += array->xstep;
+                posx += absxstep;
+            }
+            y += array->ystep;
+            posy += absystep;
+        }
+        break;
+    }
+    case 2:
+    {
+        Uint16 *pixel;
+        while (posy < array->ylen)
+        {
+            x = array->xstart;
+            posx = 0;
+            while (posx < array->xlen)
+            {
+                pixel = ((Uint16 *) (pixels + y * surface->pitch) + x);
+                *pixel = (*pixel == color) ? (Uint16) white : (Uint16) black;
+                x += array->xstep;
+                posx += absxstep;
+            }
+            y += array->ystep;
+            posy += absystep;
+        }
+        break;
+    }
+    case 3:
+    {
+        Uint8 *px;
+        Uint32 pxcolor;
+        SDL_PixelFormat *format = surface->format;
+        while (posy < array->ylen)
+        {
+            x = array->xstart;
+            posx = 0;
+            while (posx < array->xlen)
+            {
+                px = (Uint8 *) (pixels + y * surface->pitch) + x * 3;
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+                pxcolor = (px[0]) + (px[1] << 8) + (px[2] << 16);
+                if (pxcolor == color)
+                {
+                    *(px + (format->Rshift >> 3)) = (Uint8) (white >> 16);
+                    *(px + (format->Gshift >> 3)) = (Uint8) (white >> 8);
+                    *(px + (format->Bshift >> 3)) = (Uint8) white;
+                }
+                else
+                {
+                    *(px + (format->Rshift >> 3)) = (Uint8) (black >> 16);
+                    *(px + (format->Gshift >> 3)) = (Uint8) (black >> 8);
+                    *(px + (format->Bshift >> 3)) = (Uint8) black;
+                }
+#else
+                pxcolor = (px[2]) + (px[1] << 8) + (px[0] << 16);
+                if (pxcolor == dcolor)
+                {
+                    *(px + 2 - (format->Rshift >> 3)) = (Uint8) (white >> 16);
+                    *(px + 2 - (format->Gshift >> 3)) = (Uint8) (white >> 8);
+                    *(px + 2 - (format->Bshift >> 3)) = (Uint8) white;
+                }
+                else
+                {
+                    *(px + 2 - (format->Rshift >> 3)) = (Uint8) (black >> 16);
+                    *(px + 2 - (format->Gshift >> 3)) = (Uint8) (black >> 8);
+                    *(px + 2 - (format->Bshift >> 3)) = (Uint8) black;
+                }
+#endif
+                x += array->xstep;
+                posx += absxstep;
+            }
+            y += array->ystep;
+            posy += absystep;
+        }
+        break;
+    }
+    default:
+    {
+        Uint32 *pixel;
+        while (posy < array->ylen)
+        {
+            x = array->xstart;
+            posx = 0;
+            while (posx < array->xlen)
+            {
+                pixel = ((Uint32 *) (pixels + y * surface->pitch) + x);
+                *pixel = (*pixel == color) ? white : black;
+                x += array->xstep;
+                posx += absxstep;
+            }
+            y += array->ystep;
+            posy += absystep;
+        }
+        break;
+    }
+    }
+    Py_RETURN_NONE;
+}
 
 #define DOC_PIXELARRAYREPLACE "PixelArray.replace (color, replacecolor): Return None\nReplaces the passed color in the PixelArray with another one."
 
+#define DOC_PIXELARRAYEXTRACT "PixelArray.extract (color): Return None\nExtracts the passed color in the PixelArray."
+
 #define DOC_PYGAMERECT "pygame.Rect(left, top, width, height): return Rect\npygame.Rect((left, top), (width, height)): return Rect\npygame.Rect(object): return Rect\npygame object for storing rectangular coordinates"
 
 #define DOC_RECTMOVE "Rect.move(x, y): return Rect\nmoves the rectangle"

test/pixelarray_test.py

             self.assertEqual (ar[8][9], rval)
             self.assertEqual (ar[9][9], oval)
 
+    def test_extract (self):
+        for bpp in (8, 16, 24, 32):
+            sf = pygame.Surface ((10, 10), 0, bpp)
+            sf.fill ((0, 0, 255))
+            sf.fill ((255, 0, 0), (2, 2, 6, 6))
+
+            white = sf.map_rgb ((255, 255, 255))
+            black = sf.map_rgb ((0, 0, 0))
+
+            ar = pygame.PixelArray (sf)
+            ar.extract ((255, 0, 0))
+
+            self.assertEqual (ar[0][0], black)
+            self.assertEqual (ar[1][0], black)
+            self.assertEqual (ar[2][3], white)
+            self.assertEqual (ar[3][6], white)
+            self.assertEqual (ar[8][9], black)
+            self.assertEqual (ar[9][9], black)
+
 if __name__ == '__main__':
     unittest.main()