[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[pygame] Surfarray.array_alpha() bugfix, py2exe/py2app segfault



I'm not sure if my last message went though because I had not yet signed up for the mailing list before sending it, but I have an update on the issue. Sorry for the length, I'm just trying to be as helpful as possible to the pygame developers and not just slap a bandage on my problem.

In Pygame 1.8.1 and the latest 1.9.0 unstable, I've been having trouble using the surfarray module's pixels_alpha() and array_alpha() functions. I'm using 32bpp images with per-pixel alpha and I'm trying to work with the alpha data in numpy.

At first I couldn't get surfarray.array_alpha() to return a proper array (it returned all opaque values, surfarray.pixels_alpha() worked fine). Since pixels_alpha() worked fine, I figured I'd use it instead. That was fine, except it segfaulted when I tried to package up my script using py2exe or py2app. You can get a minimal testcase that shows everything I'm talking about here: http://dl-client.getdropbox.com/u/107712/alpha.zip

So I went to find out why array_alpha wasn't working properly. I investigated in the pygame source and found the culprit in "pygame/ _numpysurfarray.py"

The following code, intended to catch 8 bit images or images without alpha values, was erroneously catching my perpixel images.

    if surface.get_bytesize () == 1 or not surface.get_alpha ():
        # 1 bpp surfaces and surfaces without alpha are always fully
        # opaque.

The fix is simple, make sure that the image is less than 32bpp AND missing an alpha channel before giving up on it.

if surface.get_bytesize () == 1 or (not surface.get_alpha () and surface.get_bytesize () < 4):
        # 1 bpp surfaces and surfaces without alpha are always fully
        # opaque.

A pygame developer should make and commit that change. Once I fixed that issue, everything worked as expected... as long as I ran the script from the command line. Now if I used either array_alpha() or pixels_alpha() in a py2exe/p2app program, I got a segmentation fault! ( just like before the change with pixels_alpha() )

I tracked the segfault through the array_alpha function to the array2d function in "pygame/_numpysurfarray.py".

    # Taken from Alex Holkner's pygame-ctypes package. Thanks a lot.
    data = surface.get_buffer ().raw

From there, the line to run last before the segfault seems to reference the compiled C surface module. I looked into the module (surface.c) but I don't see anything obvious. I also checked the raw getter in _bufferproxy.c but I'm a bit over my head at this point. Why would the code run fine on the command line but segfault if bundled up? It's not an issue with Numpy because it works fine bundled into an exe or app. Pygame typically bundles well also.

I've tried all different configurations. Everything is up to date and working properly as far as I can tell. Python 2.5, Numpy 1.2.1. Both Windows XP and Mac OS X. Numpy works fine on its own in both scripts and exe/apps.

Again, here is a minimal test case that demonstrates all these issues:
http://dl-client.getdropbox.com/u/107712/alpha.zip

MAIN.PY:

#Import Modules
import os, pygame, numpy
from pygame.locals import *
from numpy import *

def main():
   pygame.init()
   screen = pygame.display.set_mode((500,500))
   image = pygame.image.load("alpha.png")
   image = image.convert_alpha()

   # Setup the pygame array system to use numpy
   pygame.surfarray.use_arraytype('numpy')

   # Copy the images' alpha values to numpy arrays
   a = pygame.surfarray.pixels_alpha(image)
   b = pygame.surfarray.array_alpha(image)
	
   print array2string(a)
   print array2string(b)
   return 0

#this calls the 'main' function when this script is executed
if __name__ == '__main__': main()