Commits

illume committed bc4b1b2

Added support to transform.scale and transform.scale2x so that a destination
surface could be passed in and used instead of creating a new one each time.

Comments (0)

Files changed (4)

 # BREAK = change breaks existing code
 # BUG	= fixed a bug that was (or could have been) crashing
 
+Jun 16, 2006
+    Allowed passing in the destination surface to the transform.scale and
+     transform.scale2x.  This is faster if reusing the surface.
+
 Jun 15, 2006
     [BUG] Font fix for empty string causing segfault.  Added unittest.
 
 
 static PyObject* surf_scale(PyObject* self, PyObject* arg)
 {
-	PyObject *surfobj;
+	PyObject *surfobj, *surfobj2;
 	SDL_Surface* surf, *newsurf;
 	int width, height;
+        surfobj2 = NULL;
+
 
 	/*get all the arguments*/
-	if(!PyArg_ParseTuple(arg, "O!(ii)", &PySurface_Type, &surfobj, &width, &height))
+	if(!PyArg_ParseTuple(arg, "O!(ii)|O!", &PySurface_Type, &surfobj, 
+                                               &width, &height, 
+                                               &PySurface_Type, &surfobj2)) {
 		return NULL;
-	surf = PySurface_AsSurface(surfobj);
+        }
+
 	if(width < 0 || height < 0)
 		return RAISE(PyExc_ValueError, "Cannot scale to negative size");
+
+	surf = PySurface_AsSurface(surfobj);
 	
-	newsurf = newsurf_fromsurf(surf, width, height);
-	if(!newsurf) return NULL;
+        if(!surfobj2) {
+
+            newsurf = newsurf_fromsurf(surf, width, height);
+            if(!newsurf) return NULL;
+        } else {
+            newsurf = PySurface_AsSurface(surfobj2);
+        }
+
+
+        /* check to see if the size is twice as big. */
+        if(newsurf->w != (width) || newsurf->h != (height)) {
+            return RAISE(PyExc_ValueError, 
+                         "Destination surface not the given width or height.");
+        }
+
+        /* check to see if the format of the surface is the same. */
+        if(surf->format->BytesPerPixel != newsurf->format->BytesPerPixel) {
+            return RAISE(PyExc_ValueError, 
+                         "Source and destination surfaces need the same format.");
+        }
 
 	if(width && height)
 	{
 		SDL_UnlockSurface(newsurf);
 	}
 
-	return PySurface_New(newsurf);
+	if(surfobj2) {
+            Py_INCREF(surfobj2);
+            return surfobj2;
+        } else {
+            return PySurface_New(newsurf);
+        }
 }
 
 
+
 static PyObject* surf_scale2x(PyObject* self, PyObject* arg)
 {
-	PyObject *surfobj;
-	SDL_Surface* surf, *newsurf;
+	PyObject *surfobj, *surfobj2;
+	SDL_Surface *surf;
+        SDL_Surface *newsurf;
 	int width, height;
+        surfobj2 = NULL;
+        
 
 	/*get all the arguments*/
-	if(!PyArg_ParseTuple(arg, "O!", &PySurface_Type, &surfobj))
-		return NULL;
+        if(!PyArg_ParseTuple(arg, "O!|O!", &PySurface_Type, &surfobj, 
+                                           &PySurface_Type, &surfobj2)) {
+            return NULL;
+        }
+
 	surf = PySurface_AsSurface(surfobj);
 
-	width = surf->w * 2;
-	height = surf->h * 2;
+        /* if the second surface is not there, then make a new one. */
+
+        if(!surfobj2) {
+            width = surf->w * 2;
+            height = surf->h * 2;
+
+            newsurf = newsurf_fromsurf(surf, width, height);
+
+            if(!newsurf) return NULL;
+        } else {
+            newsurf = PySurface_AsSurface(surfobj2);
+        }
+
 	
-	newsurf = newsurf_fromsurf(surf, width, height);
-	if(!newsurf) return NULL;
 
-	SDL_LockSurface(newsurf);
-	PySurface_Lock(surfobj);
+        /* check to see if the size is twice as big. */
+        if(newsurf->w != (surf->w * 2) || newsurf->h != (surf->h * 2)) {
+            return RAISE(PyExc_ValueError, 
+                         "Destination surface not 2x bigger.");
+        }
+
+        /* check to see if the format of the surface is the same. */
+        if(surf->format->BytesPerPixel != newsurf->format->BytesPerPixel) {
+            return RAISE(PyExc_ValueError, 
+                         "Source and destination surfaces need the same format.");
+        }
+
+        SDL_LockSurface(newsurf);
+        SDL_LockSurface(surf);
 
 	scale2x(surf, newsurf);
 
-	PySurface_Unlock(surfobj);
-	SDL_UnlockSurface(newsurf);
+        SDL_UnlockSurface(surf);
+        SDL_UnlockSurface(newsurf);
 
-	return PySurface_New(newsurf);
+	if(surfobj2) {
+            Py_INCREF(surfobj2);
+            return surfobj2;
+        } else {
+            return PySurface_New(newsurf);
+        }
 }
 
 
+
+
+
 static PyObject* surf_rotate(PyObject* self, PyObject* arg)
 {
 	PyObject *surfobj;

src/transform.doc

 
 scale
 resize to new resolution
-pygame.transform.scale(Surface, (width, height)): return Surface
+pygame.transform.scale(Surface, (width, height), DestSurface = None): return Surface
 
 Resizes the Surface to a new resolution. This is a fast scale operation
 that does not sample the results. 
+
+An optional destination surface can be used, rather than have it create 
+a new one.  This is quicker if you want to repeatedly scale something.  
+However the destination must be the same size as the (width, height) passed 
+in.  Also the destination surface must be the same format.
 <END>
 
 
 
 scale2x
 specialized image doubler
-pygame.transform.scale2x(Surface): Surface
+pygame.transform.scale2x(Surface, DestSurface = None): Surface
 
 This will return a new image that is double the size of the original. It uses
 the AdvanceMAME Scale2X algorithm which does a 'jaggie-less' scale of bitmap
 This really only has an effect on simple images with solid colors. On
 photographic and antialiased images it will look like a regular unfiltered
 scale.
+
+An optional destination surface can be used, rather than have it create 
+a new one.  This is quicker if you want to repeatedly scale something.  
+However the destination must be twice the size of the source surface passed 
+in.  Also the destination surface must be the same format.
 <END>
 
 

test/transform_test.py

 
 class TransformTest( unittest.TestCase ):
     
-    def test_scale( self ):
+    def test_scale_alpha( self ):
         """ see if set_alpha information is kept.
         """
 
         self.assertEqual(s.get_alpha(),s2.get_alpha())
 
 
+    def test_scale_destination( self ):
+        """ see if the destination surface can be passed in to use.
+        """
+
+        s = pygame.Surface((32,32))
+        s2 = pygame.transform.scale(s, (64,64))
+        s3 = s2.copy()
+
+        s3 = pygame.transform.scale(s, (64,64), s3)
+        pygame.transform.scale(s, (64,64), s2)
+
+        # the wrong size surface is past in.  Should raise an error.
+        self.assertRaises(ValueError, pygame.transform.scale, s, (33,64), s3)
+
+
+
 
 if __name__ == '__main__':
     unittest.main()