Commits

brian  committed 6c7f1d4

surface.get_bounding_rect

  • Participants
  • Parent commits c213fcb

Comments (0)

Files changed (4)

File src/pygamedocs.h

 
 #define DOC_PYGAMEMIXER "pygame module for loading and playing sounds"
 
-#define DOC_PYGAMEMIXERINIT "pygame.mixer.init(frequency=22050, size=-16, stereo=2, buffer=1024): return None\ninitialize the mixer module"
+#define DOC_PYGAMEMIXERINIT "pygame.mixer.init(frequency=22050, size=-16, channels=2, buffer=1024): return None\ninitialize the mixer module"
 
-#define DOC_PYGAMEMIXERPREINIT "pygame.mixer.pre_init(frequency=0, size=0, stereo=0, buffersize=0): return None\npreset the mixer init arguments"
+#define DOC_PYGAMEMIXERPREINIT "pygame.mixer.pre_init(frequency=0, size=0, channels=0, buffersize=0): return None\npreset the mixer init arguments"
 
 #define DOC_PYGAMEMIXERQUIT "pygame.mixer.quit(): return None\nuninitialize the mixer"
 
-#define DOC_PYGAMEMIXERGETINIT "pygame.mixer.get_init(): return (frequency, format, stereo)\ntest if the mixer is initialized"
+#define DOC_PYGAMEMIXERGETINIT "pygame.mixer.get_init(): return (frequency, format, channels)\ntest if the mixer is initialized"
 
 #define DOC_PYGAMEMIXERSTOP "pygame.mixer.stop(): return None\nstop playback of all sound channels"
 
 
 #define DOC_SURFACEGETLOSSES "Surface.get_losses(): return (R, G, B, A)\nthe significant bits used to convert between a color and a mapped integer"
 
+#define DOC_SURFACEGETBOUNDINGRECT "Surface.get_bounding_rect(min_alpha = 1): return Rect\nfind the smallest rect containing data"
+
 #define DOC_SURFACEGETBUFFER "Surface.get_buffer(): return BufferProxy\nacquires a buffer object for the pixels of the Surface."
 
 #define DOC_PYGAMESURFARRAY "pygame module for accessing surface pixel data using array interfaces"

File src/surface.c

 static PyObject *surf_get_parent (PyObject *self);
 static PyObject *surf_subsurface (PyObject *self, PyObject *args);
 static PyObject *surf_get_buffer (PyObject *self);
+static PyObject *surf_get_bounding_rect (PyObject *self, PyObject *args,
+                                          PyObject *kwargs);
 
 static struct PyMethodDef surface_methods[] =
 {
       DOC_SURFACEGETPARENT },
     { "get_abs_parent", (PyCFunction) surf_get_abs_parent, METH_NOARGS,
       DOC_SURFACEGETABSPARENT },
+    { "get_bounding_rect", (PyCFunction) surf_get_bounding_rect, METH_KEYWORDS,
+      DOC_SURFACEGETBOUNDINGRECT},
     { "get_buffer", (PyCFunction) surf_get_buffer, METH_NOARGS,
       DOC_SURFACEGETBUFFER},
 
 }
 
 static intptr_t 
-//surface_init (PySurfaceObject *self, PyObject *args, PyObject *kwds)
 surface_init (PySurfaceObject *self, PyObject *args, PyObject *kwds)
 {
     Uint32 flags = 0;
     return owner;
 }
 
+static PyObject *
+surf_get_bounding_rect (PyObject *self, PyObject *args, PyObject *kwargs)
+{
+    PyObject *rect;
+    SDL_Surface *surf = PySurface_AsSurface (self);
+    SDL_PixelFormat *format = surf->format;
+    Uint8 *pixels = (Uint8 *) surf->pixels;
+    Uint8 *pixel;
+    int x, y;
+    int min_x, min_y, max_x, max_y;
+    int min_alpha = 1;
+    int found_alpha = 0;
+    Uint8 r, g, b, a;
+    int has_colorkey = 0;
+    Uint8 keyr, keyg, keyb;
+
+    char *kwids[] = { "min_alpha", NULL };
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwids, &min_alpha))
+       return RAISE (PyExc_ValueError, "get_bounding_rect only accepts a single optional min_alpha argument");
+    
+    if (!surf)
+        return RAISE (PyExc_SDLError, "display Surface quit");
+
+    if (!PySurface_Lock (self))
+    	return RAISE (PyExc_SDLError, "could not lock surface");
+
+    if (surf->flags & SDL_SRCCOLORKEY)
+    {
+        has_colorkey = 1;
+        SDL_GetRGBA (surf->format->colorkey, surf->format, &keyr, &keyg, &keyb, &a);
+    }
+    
+    pixels = (Uint8 *) surf->pixels;
+    
+    min_y = 0;
+    min_x = 0;
+    max_x = surf->w;
+    max_y = surf->h;
+
+    found_alpha = 0;
+    for (y = max_y - 1; y >= min_y; --y)
+    {
+        for (x = min_x; x < max_x; ++x)
+        {
+            pixel = (pixels + y * surf->pitch) + x*format->BytesPerPixel;
+            SDL_GetRGBA (*((Uint32*)pixel), surf->format, &r, &g, &b, &a);
+            if (a >= min_alpha && has_colorkey == 0
+                || (has_colorkey != 0 && (r != keyr || g != keyg || b != keyb)))
+            {
+                found_alpha = 1;
+                break;
+            }
+        }
+        if (found_alpha == 1)
+        {
+            break;
+        }
+        max_y = y;
+    }
+    found_alpha = 0;
+    for (x = max_x - 1; x >= min_x; --x)
+    {
+        for (y = min_y; y < max_y; ++y)
+        {
+            pixel = (pixels + y * surf->pitch) + x*format->BytesPerPixel;
+            SDL_GetRGBA (*((Uint32*)pixel), surf->format, &r, &g, &b, &a);
+            if (a >= min_alpha && has_colorkey == 0
+                || (has_colorkey != 0 && (r != keyr || g != keyg || b != keyb)))
+            {
+                found_alpha = 1;
+                break;
+            }
+        }
+        if (found_alpha == 1)
+        {
+            break;
+        }
+        max_x = x;
+    }
+    found_alpha = 0;
+    for (y = min_y; y < max_y; ++y)
+    {
+        min_y = y;
+        for (x = min_x; x < max_x; ++x)
+        {
+            pixel = (pixels + y * surf->pitch) + x*format->BytesPerPixel;
+            SDL_GetRGBA (*((Uint32*)pixel), surf->format, &r, &g, &b, &a);
+            if (a >= min_alpha && has_colorkey == 0
+                || (has_colorkey != 0 && (r != keyr || g != keyg || b != keyb)))
+            {
+                found_alpha = 1;
+                break;
+            }
+        }
+        if (found_alpha == 1)
+        {
+            break;
+        }
+    }
+    found_alpha = 0;
+    for (x = min_x; x < max_x; ++x)
+    {
+        min_x = x;
+        for (y = min_y; y < max_y; ++y)
+        {
+            pixel = (pixels + y * surf->pitch) + x*format->BytesPerPixel;
+            SDL_GetRGBA (*((Uint32*)pixel), surf->format, &r, &g, &b, &a);
+            if (a >= min_alpha && has_colorkey == 0
+                || (has_colorkey != 0 && (r != keyr || g != keyg || b != keyb)))
+            {
+                found_alpha = 1;
+                break;
+            }
+        }
+        if (found_alpha == 1)
+        {
+            break;
+        }
+    }
+    if (!PySurface_Unlock (self))
+    	return RAISE (PyExc_SDLError, "could not unlock surface");
+
+    rect = PyRect_New4 (min_x, min_y, max_x - min_x, max_y - min_y);
+    return rect;
+}
+
 static PyObject *surf_get_buffer (PyObject *self)
 {
     PyObject *buffer;
     PyObject *lock;
     SDL_Surface *surface = PySurface_AsSurface (self);
     SDL_PixelFormat *format = surface->format;
-    size_t mod;
     Py_ssize_t length;
 
     length = (Py_ssize_t) surface->pitch * surface->h;

File src/surface.doc

 the significant bits used to convert between a color and a mapped integer
 Surface.get_losses(): return (R, G, B, A)
 
-Return the least significan number of bits stripped from each color
+Return the least significant number of bits stripped from each color
 in a mapped integer.
 
 This value is not needed for normal Pygame usage.
 <END>
 
+
+
+get_bounding_rect
+find the smallest rect containing data
+Surface.get_bounding_rect(min_alpha = 1): return Rect
+
+Returns the smallest rectangular region that contains all the pixels
+in the surface that have an alpha value greater than or equal to the
+minimum alpha value. 
+
+This function will temporarily lock and unlock the Surface as needed.
+<END>
+
+
+
 get_buffer
 acquires a buffer object for the pixels of the Surface.
 Surface.get_buffer(): return BufferProxy

File test/surface_test.py

 
 
     def test_SRCALPHA(self):
-
         # has the flag been passed in ok?
         surf = pygame.Surface((70,70), SRCALPHA, 32)
         self.assertEqual(surf.get_flags() & SRCALPHA, SRCALPHA)
 
-
         #24bit surfaces can not have SRCALPHA.
         self.assertRaises(ValueError, pygame.Surface, (100, 100), pygame.SRCALPHA, 24)
-        #s.fill((255, 0, 0))
-
-        #self.assertEqual(s.get_bitsize(), 24)
-        #self.assertEqual(s.get_bytesize(), 4)
-
 
         # if we have a 32 bit surface, the SRCALPHA should have worked too.
         surf2 = pygame.Surface((70,70), SRCALPHA)
         # 70*70*4 bytes = 19600
         self.assertEqual (repr (buf), "<BufferProxy(19600)>")
 
+    def test_get_bounding_rect (self):
+        surf = pygame.Surface ((70, 70), SRCALPHA, 32)
+        surf.fill((0,0,0,0))
+        bound_rect = surf.get_bounding_rect()
+        self.assertEqual(bound_rect.width, 0)
+        self.assertEqual(bound_rect.height, 0)
+        surf.set_at((30,30),(255,255,255,1))
+        bound_rect = surf.get_bounding_rect()
+        self.assertEqual(bound_rect.left, 30)
+        self.assertEqual(bound_rect.top, 30)
+        self.assertEqual(bound_rect.width, 1)
+        self.assertEqual(bound_rect.height, 1)
+        surf.set_at((29,29),(255,255,255,1))
+        bound_rect = surf.get_bounding_rect()
+        self.assertEqual(bound_rect.left, 29)
+        self.assertEqual(bound_rect.top, 29)
+        self.assertEqual(bound_rect.width, 2)
+        self.assertEqual(bound_rect.height, 2)
+        
+        surf = pygame.Surface ((70, 70), 0, 24)
+        surf.fill((0,0,0))
+        bound_rect = surf.get_bounding_rect()
+        self.assertEqual(bound_rect.width, surf.get_width())
+        self.assertEqual(bound_rect.height, surf.get_height())
+
+        surf.set_colorkey((0,0,0))
+        bound_rect = surf.get_bounding_rect()
+        self.assertEqual(bound_rect.width, 0)
+        self.assertEqual(bound_rect.height, 0)
+        surf.set_at((30,30),(255,255,255))
+        bound_rect = surf.get_bounding_rect()
+        self.assertEqual(bound_rect.left, 30)
+        self.assertEqual(bound_rect.top, 30)
+        self.assertEqual(bound_rect.width, 1)
+        self.assertEqual(bound_rect.height, 1)
+        surf.set_at((60,60),(255,255,255))
+        bound_rect = surf.get_bounding_rect()
+        self.assertEqual(bound_rect.left, 30)
+        self.assertEqual(bound_rect.top, 30)
+        self.assertEqual(bound_rect.width, 31)
+        self.assertEqual(bound_rect.height, 31)
+
 if __name__ == '__main__':
     unittest.main()