1. pygame
  2. Untitled project
  3. pygame

Commits

Nirav Patel  committed eeaeedc

transform module additions and changes

Increased performance in threshold, average_surfaces

Added function average_color

  • Participants
  • Parent commits 201eff6
  • Branches default

Comments (0)

Files changed (5)

File docs/ref/index.html

View file
  • Ignore whitespace
 </ul>
 <li><a href="transform.html#pygame.transform">pygame.transform</a> - <font size=-1>pygame module to transform surfaces</font></li>
 <ul>
+<li><a href="transform.html#pygame.transform.average_color">pygame.transform.average_color</a> - <font size=-1>finds the average color of a surface</font></li>
 <li><a href="transform.html#pygame.transform.average_surfaces">pygame.transform.average_surfaces</a> - <font size=-1>find the average surface from many surfaces.</font></li>
 <li><a href="transform.html#pygame.transform.chop">pygame.transform.chop</a> - <font size=-1>gets a copy of an image with an interior area removed</font></li>
 <li><a href="transform.html#pygame.transform.flip">pygame.transform.flip</a> - <font size=-1>flip vertically and horizontally</font></li>

File docs/ref/transform.html

View file
  • Ignore whitespace
   <tr><td><a href="transform.html#pygame.transform.chop">pygame.transform.chop</a> - <font size=-1>gets a copy of an image with an interior area removed</font></td><td>gets a copy of an image with an interior area removed</td></tr>
   <tr><td><a href="transform.html#pygame.transform.laplacian">pygame.transform.laplacian</a> - <font size=-1>find edges in a surface</font></td><td>find edges in a surface</td></tr>
   <tr><td><a href="transform.html#pygame.transform.average_surfaces">pygame.transform.average_surfaces</a> - <font size=-1>find the average surface from many surfaces.</font></td><td>find the average surface from many surfaces.</td></tr>
+  <tr><td><a href="transform.html#pygame.transform.average_color">pygame.transform.average_color</a> - <font size=-1>finds the average color of a surface</font></td><td>finds the average color of a surface</td></tr>
   <tr><td><a href="transform.html#pygame.transform.threshold">pygame.transform.threshold</a> - <font size=-1>finds which, and how many pixels in a surface are within a threshold of a color.</font></td><td>finds which, and how many pixels in a surface are within a threshold of a color.</td></tr>
 </table></small></ul>
 <p><tt>A</tt> Surface transform is an operation that moves or resizes the pixels. All these functions take a Surface to operate on and return a new Surface with the results. </p>
 <br></ul>
 
 
+<a name="pygame.transform.average_color">
+<big><b>pygame.transform.average_color</big></b><br><ul>
+  <i>finds the average color of a surface</i><br>
+  <tt>pygame.transform.average_color(Surface, Rect = None): return Color</tt><br>
+<p>Finds the average color of a Surface or a region of a surface specified by a Rect, and returns it as a Color. </p>
+<!--COMMENTS:pygame.transform.average_color--> &nbsp;<br> 
+<br></ul>
+
+
 <a name="pygame.transform.threshold">
 <big><b>pygame.transform.threshold</big></b><br><ul>
   <i>finds which, and how many pixels in a surface are within a threshold of a color.</i><br>
-<p><tt>pygame.transform.threshold(DestSurface</tt>, Surface, color, threshold = (0,0,0,0), diff_color = (0,0,0,0), change_return = True, Surface =None): return num_threshold_pixels </p>
-<p>It can set the destination surface where all of the pixels not within the threshold are changed to diff_color. </p>
+  <tt>pygame.transform.threshold(DestSurface, Surface, color, threshold = (0,0,0,0), diff_color = (0,0,0,0), change_return = True, Surface = None, inverse = False): return num_threshold_pixels</tt><br>
+<p>Finds which, and how many pixels in a surface are within a threshold of a color. </p>
+<p>It can set the destination surface where all of the pixels not within the threshold are changed to diff_color. If inverse is optionally set to True, the pixels that are within the threshold are instead changed to diff_color. </p>
+<p>If the optional second surface is given, it is used to threshold against rather than the specified color. That is, it will find each pixel in the first Surface that is within the threshold of the pixel at the same coordinates of the second Surface. If change_return is set, the pixels set in DestSurface will be those from the first Surface. </p>
 <p>Or it can be used to just count the number of pixels within the threshold if you set change_return to False. </p>
-<p>When given the optional third surface, it will use the colors in that rather than the 3rd position "color" arg. </p>
 <p>You can use a threshold of (r,g,b,a) where the r,g,b can have different thresholds. So you could use an r threshold of 40 and a blue threshold of 2 if you like. </p>
 <p>New in pygame <tt>1.8</tt> </p>
 <!--COMMENTS:pygame.transform.threshold--> &nbsp;<br> 

File src/pygamedocs.h

View file
  • Ignore whitespace
 
 #define DOC_PYGAMETRANSFORMAVERAGESURFACES "pygame.transform.average_surfaces(Surfaces, DestSurface = None): return Surface\nfind the average surface from many surfaces."
 
-#define DOC_PYGAMETRANSFORMTHRESHOLD "finds which, and how many pixels in a surface are within a threshold of a color."
+#define DOC_PYGAMETRANSFORMAVERAGECOLOR "pygame.transform.average_color(Surface, Rect = None): return Color\nfinds the average color of a surface"
 
+#define DOC_PYGAMETRANSFORMTHRESHOLD "pygame.transform.threshold(DestSurface, Surface, color, threshold = (0,0,0,0), diff_color = (0,0,0,0), change_return = True, Surface = None, inverse = False): return num_threshold_pixels\nfinds which, and how many pixels in a surface are within a threshold of a color."
+

File src/transform.c

View file
  • Ignore whitespace
 
 
 
-static int
-get_threshold (SDL_Surface *destsurf, SDL_Surface *surf, SDL_Surface *surf2, Uint32 color,  Uint32 threshold,  Uint32 diff_color, int change_return) {
-
-
-    int x, y;
+static int get_threshold (SDL_Surface *destsurf, SDL_Surface *surf,
+                          SDL_Surface *surf2, Uint32 color,  Uint32 threshold,
+                          Uint32 diff_color, int change_return, int inverse)
+{
+    int x, y, result, similar, rshift, gshift, bshift, rshift2, gshift2, bshift2;
     Uint8 *pixels, *destpixels, *pixels2;
     SDL_Rect sdlrect;
-
-
     SDL_PixelFormat *format, *destformat, *format2;
-    Uint32 the_color, the_color2;
-    Uint8 *pix;
+    Uint32 the_color, the_color2, rmask, gmask, bmask, rmask2, gmask2, bmask2;
+    Uint8 *pix, *byte_buf;
     Uint8 r, g, b, a;
     Uint8 dr, dg, db, da;
     Uint8 tr, tg, tb, ta;
 
-    Uint8 c1r, c1g, c1b, c1a;
-    Uint8 c2r, c2g, c2b, c2a;
-
-
-    Uint8 *byte_buf;
-
-    int result;
-
-    int similar;
-
     similar = 0;
-
-
     pixels = (Uint8 *) surf->pixels;
     format = surf->format;
-
-
-    SDL_GetRGBA (diff_color, format, &dr, &dg, &db, &da);
-    /*
-    printf("color:%d:   %d, %d, %d, %d,   change_return:%d: \n", diff_color, dr,dg,db,da, change_return);
-    */
-
+    rmask = format->Rmask;
+    gmask = format->Gmask;
+    bmask = format->Bmask;
+    rshift = format->Rshift;
+    gshift = format->Gshift;
+    bshift = format->Bshift;
 
     if(change_return) {
         sdlrect.x = sdlrect.y = 0;
         sdlrect.w = destsurf->w;
         sdlrect.h = destsurf->h;
+        destpixels = (Uint8 *) destsurf->pixels;
+        destformat = destsurf->format;
         result = SDL_FillRect (destsurf, &sdlrect, diff_color);
+    } else { /* make gcc stop complaining */
+        destpixels = NULL;
+        destformat = NULL;
+    }
+    
+    if(surf2) {
+        format2 = surf2->format;
+        rmask2 = format2->Rmask;
+        gmask2 = format2->Gmask;
+        bmask2 = format2->Bmask;
+        rshift2 = format2->Rshift;
+        gshift2 = format2->Gshift;
+        bshift2 = format2->Bshift;
+        pixels2 = (Uint8 *) surf2->pixels;
+    } else { /* make gcc stop complaining */
+        rmask2 = gmask2 = bmask2 = 0;
+        rshift2 = gshift2 = bshift2 = 0;
+        format2 = NULL;
+        pixels2 = NULL;
     }
 
-
-
     SDL_GetRGBA (color, format, &r, &g, &b, &a);
-
-/*
-    printf("color:%d:   %d, %d, %d, %d\n", color, r,g,b,a);
-*/
-
     SDL_GetRGBA (threshold, format, &tr, &tg, &tb, &ta);
-
-
-
-
-
-
-/*
-    printf(":%d, %d, %d, %d\n", rgba_threshold[0], rgba_threshold[1], rgba_threshold[2], rgba_threshold[3]);
-    printf(":%d, %d, %d, %d\n", rgba_diff_color[0], rgba_diff_color[1], rgba_diff_color[2], rgba_diff_color[3]);
-    printf(":%d\n", change_return);
-*/
-
-
-    /* TODO: this is the slow, but easy to code way.  Could make the loop 
-     *         just increment a pointer depending on the format.  
-     *         It's faster than in python anyhow.
-     */
-    if(destsurf) {
-        destpixels = (Uint8 *) destsurf->pixels;
-        destformat = destsurf->format;
-    }
-
-    if(surf2) {
-        pixels2 = (Uint8 *) surf2->pixels;
-        format2 = surf2->format;
-    }
-
-
-
-    /*
-    printf("surf->w:%d, surf->h:%d\n", surf->w, surf->h);
-    printf(" ----- %d", surf2);
-    */
-
-
-
-
+    SDL_GetRGBA (diff_color, format, &dr, &dg, &db, &da);
 
     for(y=0; y < surf->h; y++) {
+        pixels = surf->pixels + y*surf->pitch;
+        if (surf2) {
+            pixels2 = surf2->pixels + y*surf2->pitch;
+        }
         for(x=0; x < surf->w; x++) {
             /* the_color = surf->get_at(x,y) */
             switch (format->BytesPerPixel)
             {
             case 1:
-                the_color = (Uint32)*((Uint8 *) pixels + y * surf->pitch + x);
+                the_color = (Uint32)*((Uint8 *) pixels);
+                pixels++;
                 break;
             case 2:
-                the_color = (Uint32)*((Uint16 *) (pixels + y * surf->pitch) + x);
+                the_color = (Uint32)*((Uint16 *) pixels);
+                pixels += 2;
                 break;
             case 3:
-                pix = ((Uint8 *) (pixels + y * surf->pitch) + x * 3);
-        #if SDL_BYTEORDER == SDL_LIL_ENDIAN
+                pix = ((Uint8 *) pixels);
+                pixels += 3;
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
                 the_color = (pix[0]) + (pix[1] << 8) + (pix[2] << 16);
-        #else
+#else
                 the_color = (pix[2]) + (pix[1] << 8) + (pix[0] << 16);
-        #endif
+#endif
                 break;
             default:                  /* case 4: */
-                the_color = *((Uint32 *) (pixels + y * surf->pitch) + x);
+                the_color = *((Uint32 *) pixels);
+                pixels += 4;
                 break;
             }
 
-            SDL_GetRGBA (the_color, format, &c1r, &c1g, &c1b, &c1a);
-
-
-            /*
-            See if we are using another surface or not.
-            If we are, get the other surfaces pixel.
-
-            Then test the threshold against that pixels color.
-            */
-
-            if(surf2) {
-                /* the_color2 = surf2->get_at(x,y) */
-
-                switch (format2->BytesPerPixel)
-                {
-                case 1:
-                    the_color2 = (Uint32)*((Uint8 *) pixels2 + y * surf2->pitch + x);
-                    break;
-                case 2:
-                    the_color2 = (Uint32)*((Uint16 *) (pixels2 + y * surf2->pitch) + x);
-                    break;
-                case 3:
-                    pix = ((Uint8 *) (pixels2 + y * surf2->pitch) + x * 3);
-            #if SDL_BYTEORDER == SDL_LIL_ENDIAN
-                    the_color2 = (pix[0]) + (pix[1] << 8) + (pix[2] << 16);
-            #else
-                    the_color2 = (pix[2]) + (pix[1] << 8) + (pix[0] << 16);
-            #endif
-                    break;
-                default:                  /* case 4: */
-                    the_color2 = *((Uint32 *) (pixels2 + y * surf2->pitch) + x);
-                    break;
+            if (surf2) {
+                switch (format2->BytesPerPixel) {
+                    case 1:
+                        the_color2 = (Uint32)*((Uint8 *) pixels2);
+                        pixels2++;
+                        break;
+                    case 2:
+                        the_color2 = (Uint32)*((Uint16 *) pixels2);
+                        pixels2 += 2;
+                        break;
+                    case 3:
+                        pix = ((Uint8 *) pixels2);
+                        pixels2 += 3;
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+                        the_color2 = (pix[0]) + (pix[1] << 8) + (pix[2] << 16);
+#else
+                        the_color2 = (pix[2]) + (pix[1] << 8) + (pix[0] << 16);
+#endif
+                        break;
+                    default:                  /* case 4: */
+                        the_color2 = *((Uint32 *) pixels2);
+                        pixels2 += 4;
+                        break;
                 }
-
-                SDL_GetRGBA (the_color2, format2, &c2r, &c2g, &c2b, &c2a);
-            }
-
-
-
-
-
-            /*
-            printf("hello!  %d:%d:%d:  tr:%d\n", cr, r, abs(cr - r), tr);
-            */
-
-            if ( !surf2 && ((abs(c1r - r) < tr) &
-                            (abs(c1g - g) < tg) & 
-                            (abs(c1b - b) < tb)) ) {
-                /*
-                printf("simiar\n");
-                */
+                
+                if (((abs(((the_color2 & rmask2) >> rshift2) - ((the_color & rmask) >> rshift)) < tr) & 
+                    (abs(((the_color2 & gmask2) >> gshift2) - ((the_color & gmask) >> gshift)) < tg) & 
+                    (abs(((the_color2 & bmask2) >> bshift2) - ((the_color & bmask) >> bshift)) < tb))
+                    ^ inverse) {
+                    /* this pixel is within the threshold. */
+                    if (change_return) {
+                        /* destsurf->set_at((x,y), the_color) */
+                        switch (destformat->BytesPerPixel) {
+                            case 1:
+                                *((Uint8 *) destpixels + y * destsurf->pitch + x) = (Uint8) the_color;
+                                break;
+                            case 2:
+                                *((Uint16 *) (destpixels + y * destsurf->pitch) + x) = (Uint16) the_color;
+                                break;
+                            case 3:
+                                byte_buf = (Uint8 *) (destpixels + y * destsurf->pitch) + x * 3;
+#if (SDL_BYTEORDER == SDL_LIL_ENDIAN)
+                                *(byte_buf + (destformat->Rshift >> 3)) = (Uint8) (the_color >> 16);
+                                *(byte_buf + (destformat->Gshift >> 3)) = (Uint8) (the_color >> 8);
+                                *(byte_buf + (destformat->Bshift >> 3)) = (Uint8) the_color;
+#else
+                                *(byte_buf + 2 - (destformat->Rshift >> 3)) = (Uint8) (the_color >> 16);
+                                *(byte_buf + 2 - (destformat->Gshift >> 3)) = (Uint8) (the_color >> 8);
+                                *(byte_buf + 2 - (destformat->Bshift >> 3)) = (Uint8) the_color;
+#endif
+                                break;
+                            default:                  /* case 4: */
+                                *((Uint32 *) (destpixels + y * destsurf->pitch) + x) = the_color;
+                                break;
+                        }
+                    }
+                    similar++;
+                }
+                
+            } else if (((abs(((the_color & rmask) >> rshift) - r) < tr) & 
+                 (abs(((the_color & gmask) >> gshift) - g) < tg) & 
+                 (abs(((the_color & bmask) >> bshift) - b) < tb))
+                 ^ inverse) {
 
                 /* this pixel is within the threshold. */
                 if (change_return) {
                     /* destsurf->set_at((x,y), the_color) */
-
-
                     switch (destformat->BytesPerPixel)
                     {
                     case 1:
                         break;
                     }
                 }
-
-
-
                 similar++;
-            } else if (surf2 && ((abs(c1r - c2r) < tr) &
-                                 (abs(c1g - c2g) < tg) & 
-                                 (abs(c1b - c2b) < tb))  ) {
-
-                /*
-                printf("in here!\n");
-                */
-
-                /* see if we are changing the return surface, 
-                     and how we want to change it.
-                */
-
-                if (change_return == 1) {
-                    /* destsurf->set_at((x,y), color)*/
-
-
-                    switch (destformat->BytesPerPixel)
-                    {
-                    case 1:
-                        *((Uint8 *) destpixels + y * destsurf->pitch + x) = (Uint8) color;
-                        break;
-                    case 2:
-                        *((Uint16 *) (destpixels + y * destsurf->pitch) + x) = (Uint16) color;
-                        break;
-                    case 3:
-                        byte_buf = (Uint8 *) (destpixels + y * destsurf->pitch) + x * 3;
-#if (SDL_BYTEORDER == SDL_LIL_ENDIAN)
-                        *(byte_buf + (destformat->Rshift >> 3)) = (Uint8) (color >> 16);
-                        *(byte_buf + (destformat->Gshift >> 3)) = (Uint8) (color >> 8);
-                        *(byte_buf + (destformat->Bshift >> 3)) = (Uint8) color;
-#else
-                        *(byte_buf + 2 - (destformat->Rshift >> 3)) = (Uint8) (color >> 16);
-                        *(byte_buf + 2 - (destformat->Gshift >> 3)) = (Uint8) (color >> 8);
-                        *(byte_buf + 2 - (destformat->Bshift >> 3)) = (Uint8) color;
-#endif
-                        break;
-                    default:                  /* case 4: */
-                        *((Uint32 *) (destpixels + y * destsurf->pitch) + x) = color;
-                        break;
-                    }
-
-                }
-                    similar++;
-
-
-
-
             }
-
-
         }
     }
-
-
-
     return similar;
 }
 
 
 
 
-
-
 static PyObject* surf_threshold(PyObject* self, PyObject* arg)
 {
-	PyObject *surfobj, *surfobj2, *surfobj3;
-	SDL_Surface* surf, *destsurf, *surf2;
-	int bpp, change_return;
+    PyObject *surfobj, *surfobj2, *surfobj3;
+    SDL_Surface* surf, *destsurf, *surf2;
+    int bpp, change_return, inverse;
     int num_threshold_pixels;
 
 
 
     num_threshold_pixels = 0;
     change_return = 1;
+    inverse = 0;
 
     rgba_threshold[0] = 0; rgba_threshold[1] = 0; rgba_threshold[2] = 0; rgba_threshold[3] = 255;
     rgba_diff_color[0] = 0; rgba_diff_color[1] = 0; rgba_diff_color[2] = 0; rgba_diff_color[3] = 255;
 
 
     /*get all the arguments*/
-    if (!PyArg_ParseTuple (arg, "O!O!O|OOiO!", &PySurface_Type, &surfobj, 
+    if (!PyArg_ParseTuple (arg, "O!O!O|OOiO!i", &PySurface_Type, &surfobj, 
                            &PySurface_Type, &surfobj2,
                            &rgba_obj_color,  &rgba_obj_threshold, &rgba_obj_diff_color, 
                            &change_return,
-                           &PySurface_Type, &surfobj3))
+                           &PySurface_Type, &surfobj3, &inverse))
         return NULL;
 
 
 
 
 
-    if (PyInt_Check (rgba_obj_color))
-    {
+    if (PyInt_Check (rgba_obj_color)) {
         color = (Uint32) PyInt_AsLong (rgba_obj_color);
-    }
-    else if (PyLong_Check (rgba_obj_color))
-    {
+    } else if (PyLong_Check (rgba_obj_color)) {
         color = (Uint32) PyLong_AsUnsignedLong (rgba_obj_color);
     }
-    else if (RGBAFromColorObj (rgba_obj_color, rgba_color))
-    {
+    else if (RGBAFromColorObj (rgba_obj_color, rgba_color)) {
         color = SDL_MapRGBA (surf->format, rgba_color[0], rgba_color[1],
             rgba_color[2], rgba_color[3]);
-        /*printf("here I am! :%d:  %d, %d, %d, %d\n", color, rgba_color[0], rgba_color[1], rgba_color[2], rgba_color[3]);
-        */
-
-    }
-    else
-    {
+    } else {
         return RAISE (PyExc_TypeError, "invalid color argument");
     }
 
-
-
     if(rgba_obj_threshold) {
 
         if (PyInt_Check (rgba_obj_threshold))
         color_diff_color = SDL_MapRGBA (surf->format, rgba_diff_color[0], rgba_diff_color[1], rgba_diff_color[2], rgba_diff_color[3]);
     }
 
-/*
-    printf(":%d, %d, %d, %d\n", rgba_color[0], rgba_color[1], rgba_color[2], rgba_color[3]);
-    printf(":%d, %d, %d, %d\n", rgba_threshold[0], rgba_threshold[1], rgba_threshold[2], rgba_threshold[3]);
-    printf(":%d, %d, %d, %d\n", rgba_diff_color[0], rgba_diff_color[1], rgba_diff_color[2], rgba_diff_color[3]);
-    printf(":%d\n", change_return);
-*/
-
-
     bpp = surf->format->BytesPerPixel;
-    /*if(bpp < 3 || bpp > 4)
-		return RAISE(PyExc_ValueError, "Only 24-bit or 32-bit surfaces can be thresholded");
-    */
-
 	
     PySurface_Lock(surfobj);
     PySurface_Lock(surfobj2);
     Py_BEGIN_ALLOW_THREADS;
 
 
-    num_threshold_pixels = get_threshold (destsurf, surf, surf2, color,  color_threshold,  color_diff_color, change_return);
+    num_threshold_pixels = get_threshold (destsurf, surf, surf2, color,  color_threshold,  color_diff_color, change_return, inverse);
 
 
     Py_END_ALLOW_THREADS;
         PySurface_Unlock(surfobj3);
     }
 
-
-
     return PyInt_FromLong (num_threshold_pixels);
 }
 
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 /*
 
 TODO:
     Uint32 the_color;
     SDL_Surface *surf;
     int height, width, x, y, surf_idx;
-    Uint8 c1r, c1g, c1b;
 
     float div_inv;
 
     Uint8 *pix;
     Uint8 *byte_buf;
     
+    Uint32 rmask, gmask, bmask;
+    int rshift, gshift, bshift;
 
     if(!num_surfaces) { return 0; }
     
     
         pixels = (Uint8 *) surf->pixels;
         format = surf->format;
+        rmask = format->Rmask;
+        gmask = format->Gmask;
+        bmask = format->Bmask;
+        rshift = format->Rshift;
+        gshift = format->Gshift;
+        bshift = format->Bshift;
     
         the_idx = accumulate;
         for(y=0;y<height;y++) {
             for(x=0;x<width;x++) {
                 SURF_GET_AT(the_color, surf, x, y, pixels, format, pix);
-                SDL_GetRGB (the_color, format, &c1r, &c1g, &c1b);
         
-                *(the_idx) += c1r;
-                *(the_idx + 1) += c1g;
-                *(the_idx + 2) += c1b;
+                *(the_idx) += (the_color & rmask) >> rshift;
+                *(the_idx + 1) += (the_color & gmask) >> gshift;
+                *(the_idx + 2) += (the_color & bmask) >> bshift;
                 the_idx += 3;
             }
         }
 static PyObject*
 surf_average_surfaces (PyObject* self, PyObject* arg)
 {
-    PyObject *surfobj, *surfobj2;
+    PyObject *surfobj2;
     SDL_Surface *surf;
     SDL_Surface *newsurf;
     SDL_Surface **surfaces;
 
 
     surfobj2 = NULL;
+    newsurf = NULL;
 
     if (!PyArg_ParseTuple (arg, "O|O!", &list, &PySurface_Type, &surfobj2))
         return NULL;
 }
 
 
+Uint32 average_color(SDL_Surface* surf, int x, int y, int width, int height) {
+    Uint32 color, rmask, gmask, bmask, amask;
+    Uint8 *pixels, *pix;
+    unsigned int rtot, gtot, btot, atot, row, col, size, rshift, gshift, bshift, ashift;
+    SDL_PixelFormat *format;
 
+    pixels = (Uint8 *) surf->pixels;
+    format = surf->format;
+    rmask = format->Rmask;
+    gmask = format->Gmask;
+    bmask = format->Bmask;
+    amask = format->Amask;
+    rshift = format->Rshift;
+    gshift = format->Gshift;
+    bshift = format->Bshift;
+    ashift = format->Ashift;
+    rtot = gtot = btot = atot = 0;
+    
+    /* make sure the area specified is within the Surface */
+    if ((x + width) > surf->w)
+        width = surf->w - x;
+    if ((y + height) > surf->h)
+        height = surf->h - y;
+    if (x < 0)
+    {
+        width -= (-x);
+        x = 0;
+    }
+    if (y < 0)
+    {
+        height -= (-y);
+        y = 0;
+    }
+    
+    size = width*height;
 
+    switch (format->BytesPerPixel) {
+        case 1:
+            for (row = y; row < y+height; row++) {
+                pixels = surf->pixels + y*surf->pitch + x;
+                for (col = x; col < x+width; col++) {
+                    color = (Uint32)*((Uint8 *) pixels);
+                    rtot += (color & rmask) >> rshift;
+                    gtot += (color & gmask) >> gshift;
+                    btot += (color & bmask) >> bshift;
+                    atot += (color & amask) >> ashift;
+                    pixels++;
+                }
+            }
+            break;    
+        case 2:
+            for (row = y; row < y+height; row++) {
+                pixels = surf->pixels + y*surf->pitch + x*2;
+                for (col = x; col < x+width; col++) {
+                    color = (Uint32)*((Uint16 *) pixels);
+                    rtot += (color & rmask) >> rshift;
+                    gtot += (color & gmask) >> gshift;
+                    btot += (color & bmask) >> bshift;
+                    atot += (color & amask) >> ashift;
+                    pixels += 2;
+                }
+            }
+            break;    
+        case 3:
+            for (row = y; row < y+height; row++) {
+                pixels = surf->pixels + y*surf->pitch + x*3;
+                for (col = x; col < x+width; col++) {
+                    pix = ((Uint8 *) pixels);
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+                    color = (pix[0]) + (pix[1] << 8) + (pix[2] << 16);
+#else
+                    color = (pix[2]) + (pix[1] << 8) + (pix[0] << 16);
+#endif
+                    rtot += (color & rmask) >> rshift;
+                    gtot += (color & gmask) >> gshift;
+                    btot += (color & bmask) >> bshift;
+                    atot += (color & amask) >> ashift;
+                    pixels += 3;
+                }
+            }                    
+            break;
+        default:                  /* case 4: */
+            for (row = y; row < y+height; row++) {
+                pixels = surf->pixels + y*surf->pitch + x*2;
+                for (col = x; col < x+width; col++) {
+                    color = (Uint32) *pixels;
+                    rtot += (color & rmask) >> rshift;
+                    gtot += (color & gmask) >> gshift;
+                    btot += (color & bmask) >> bshift;
+                    atot += (color & amask) >> ashift;
+                    pixels += 4;
+                }
+            }
+            break; 
+    }
 
+    return SDL_MapRGBA(format, (Uint8) (rtot/size),(Uint8) (gtot/size),
+                (Uint8) (btot/size),(Uint8) (atot/size));
+}
 
+static PyObject* surf_average_color(PyObject* self, PyObject* arg)
+{
+    PyObject *surfobj, *rectobj = NULL;
+    SDL_Surface* surf;
+    GAME_Rect* rect, temp;
+    Uint32 average;
+    Uint8 r, g, b, a;
 
-
-
-
-
-
-
+    if (!PyArg_ParseTuple (arg, "O!|O", &PySurface_Type, &surfobj, &rectobj))
+        return NULL;
+    
+    surf = PySurface_AsSurface (surfobj);   
+    PySurface_Lock (surfobj);
+    Py_BEGIN_ALLOW_THREADS;
+    if (!rectobj) {
+        average = average_color(surf, 0, 0, surf->w, surf->h);
+    } else {
+        if (!(rect = GameRect_FromObject (rectobj, &temp)))
+            return RAISE (PyExc_TypeError, "Rect argument is invalid");
+        average = average_color(surf, rect->x, rect->y, rect->w, rect->h);
+    }
+    
+    SDL_GetRGBA (average, surf->format, &r, &g, &b, &a);
+    Py_END_ALLOW_THREADS;
+    PySurface_Unlock (surfobj);
+    return Py_BuildValue ("(bbbb)", r, g, b, a);
+}   
 
 static PyMethodDef transform_builtins[] =
 {
     { "threshold", surf_threshold, METH_VARARGS, DOC_PYGAMETRANSFORMTHRESHOLD },
     { "laplacian", surf_laplacian, METH_VARARGS, DOC_PYGAMETRANSFORMTHRESHOLD },
     { "average_surfaces", surf_average_surfaces, METH_VARARGS, DOC_PYGAMETRANSFORMAVERAGESURFACES },
+    { "average_color", surf_average_color, METH_VARARGS, DOC_PYGAMETRANSFORMAVERAGECOLOR },
     
     { NULL, NULL, 0, NULL }
 };

File src/transform.doc

View file
  • Ignore whitespace
 New in pygame 1.8
 <END>
 
+average_color
+finds the average color of a surface
+pygame.transform.average_color(Surface, Rect = None): return Color
 
+Finds the average color of a Surface or a region of a surface specified by a
+Rect, and returns it as a Color.
+<END>
 
 threshold
 finds which, and how many pixels in a surface are within a threshold of a color.
+pygame.transform.threshold(DestSurface, Surface, color, threshold = (0,0,0,0), diff_color = (0,0,0,0), change_return = True, Surface = None, inverse = False): return num_threshold_pixels
 
-pygame.transform.threshold(DestSurface, Surface, color, threshold = (0,0,0,0), diff_color = (0,0,0,0), change_return = True, Surface =None): return num_threshold_pixels
+Finds which, and how many pixels in a surface are within a threshold of a color.
 
 It can set the destination surface where all of the pixels not within the 
-threshold are changed to diff_color.
+threshold are changed to diff_color.  If inverse is optionally set to True, the
+pixels that are within the threshold are instead changed to diff_color.
+
+If the optional second surface is given, it is used to threshold against
+rather than the specified color.  That is, it will find each pixel in the first
+Surface that is within the threshold of the pixel at the same coordinates of
+the second Surface.  If change_return is set, the pixels set in DestSurface will
+be those from the first Surface.
 
 Or it can be used to just count the number of pixels within the threshold if you set
 change_return to False.
 
-When given the optional third surface, it will use the colors in that rather 
-than the 3rd position "color" arg.
-
 You can use a threshold of (r,g,b,a) where the r,g,b can have different thresholds. So
 you could use an r threshold of 40 and a blue threshold of 2 if you like.