[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[pygame] Simpler scaling method with surfarray



-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi everyone,

I've been playing with the surfarray module and, after perusing the Numeric 
docs, I have found another method to scale up an image besides the one on the 
surfarray tutorial, faster and simpler:

    if imgarray.shape[0] >= imgarray.shape[1]:
        scaleup = N.repeat(N.repeat(imgarray, 4, 1), 4, 0)
    else:
        scaleup = N.repeat(N.repeat(imgarray, 4, 0), 4, 1)

The function 'repeat' repeats the rows/columns of the given array (first 
parameter) in the given axis (third parameter) the given number of times 
(second parameter). What the code above does is repeat the image columns four 
times and then repeat the rows four times.

By some reason, the snippet above executes faster if the smaller axis is 
repeated before the larger. Doing it in the reverse order will slow down the 
method considerably. For example, scaling the default surfarray image 2x, but 
with reversed axis order, makes the N.repeat method 1% _slower_ than the 
method on the surfarray intro!

The real merit of this other way is that it is trivial to extend it to other 
scaling factors. Making things the original way, by increment slicing, is 
possible, and somewhat simple, but optimizing it (like done on the sample 
file included, benchmark.py) is not.

                    |  Old method  |  New method  |  Savings  |
      --------------+--------------+--------------+-----------+
        2x scaling  |     6.3 s    |     4.7 s    |   25.8%   |
        3x scaling  |    13.9 s    |     8.2 s    |   41.3%   |
        4x scaling  |    23.3 s    |    12.5 s    |   46.4%   |
                          
It'd be worth including this somewhere -- maybe in the surfarray intro, maybe 
in the PCR. What do you think?

- --
Fábio Dias
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.4 (GNU/Linux)
Comment: For info see http://www.gnupg.org

iEYEARECAAYFAjwOol8ACgkQalOQFrvzGQrvbwCgk/YJp+/Zar4IFfUN+v/CPXbZ
59kAn1izmtAYjGH/0rH0fl2UYVlzb1K8
=aSzT
-----END PGP SIGNATURE-----
import os
import time
try:
    import pygame
    import pygame.image
    import Numeric as N
    import pygame.surfarray as surfarray
    from pygame.locals import *
except ImportError:
    raise ImportError, 'Error Importing Pygame/surfarray/image or Numeric'

pygame.init()
print 'Press the mouse button to advance image.'
print 'Press the "s" key to save the current image.'

def surfdemo_show(array_img, name):
    "displays a surface, waits for user to continue"
    screen = pygame.display.set_mode(array_img.shape[:2], 0, 32)
    surfarray.blit_array(screen, array_img)
    pygame.display.flip()
    pygame.display.set_caption(name)
    while 1:
        e = pygame.event.poll()
        if e.type == MOUSEBUTTONDOWN: break
        elif e.type == KEYDOWN and e.key == K_s:
            pygame.image.save(screen, name+'.bmp')
        elif e.type == QUIT: raise SystemExit

#imgarray
imagename = os.path.join('data', 'arraydemo.bmp')
imgsurface = pygame.image.load(imagename)
imgarray = surfarray.array2d(imgsurface)

start1 = time.time()
for i in range(100):
    size = N.array(imgarray.shape)*4
    scaleup = N.zeros(size)
    scaleup[::4,::4] = scaleup[2::4,::4] = imgarray
    scaleup[1::2,::4] = scaleup[::2,::4]
    scaleup[:,2::4] = scaleup[:,::4]
    scaleup[:,1::2] = scaleup[:,::2]
end1 = time.time()
print 'Old method: %3.1f s' % (end1 - start1)
surfdemo_show(scaleup, 'scaleup')


start2 = time.time()
for i in range(100):
    if imgarray.shape[0] >= imgarray.shape[1]:
        scaleup = N.repeat(N.repeat(imgarray, 4, 1), 4, 0)
    else:
        scaleup = N.repeat(N.repeat(imgarray, 4, 0), 4, 1)
end2 = time.time()
print 'New method: %3.1f s' % (end2 - start2)
print 'Savings: %3.1f%%' % ((1 - (end2 - start2)/float(end1 - start1)) * 100)
surfdemo_show(scaleup, 'scaleup')