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

Re: [pygame] Exception in _numpysurfarray.py



Marcus von Appen wrote:
On, Wed Apr 09, 2008, Lorenz Quack wrote:

Hi all,

a friend of mine had a problem using pygame.surarray.pixels3d
creation would raise the following Exception:

File "C:\Python25\lib\site-packages\pygame\surfarray.py", line 165, in pixels3d
    return numpysf.pixels3d (surface)
File "C:\Python25\lib\site-packages\pygame\_numpysurfarray.py", line 213, in pixels3d
    array.shape  = surface.get_width (), surface.get_height (), bpp
AttributeError: incompatible shape for a non-contiguous array

here is the code section in question from the _numpysurfarray.py:

    array = numpy.frombuffer (surface.get_buffer (), numpy.uint8)
    array.shape = surface.get_height (), surface.get_pitch ()
    # I believe this line make the array in some cases non-contiguous
    array = array[:,:surface.get_width () * bpp]
    # the next line raises the exception
    array.shape  = surface.get_width (), surface.get_height (), bpp
    array = array[:,:,start:end:step]
    return array

My analysis was that the line before makes the array non-contiguous and thus the direct assignment of the shape attribute fails. reshape copies the data to a new array if necessary. I might be wrong since I never had this problem myself (it might be due to the fact that I'm on Linux while my friend is using MS Windows).

I attached a patch that uses reshape instead of the direct assignment.
I left all the other places where array.shape is assigned untouched because they are mostly directly after the arrays creation and should therefor always be contiguous.

Please can someone (with more numpy experience than myself) look at this?

Interesting issue, I cannot reproduce it. Can you please post the code
that caused the error, so I can verify whether there might be other
glitches as well?
Regards
Marcus

I would try to provide a minimal code which reproduces the error but since I don't experience it myself I can't do that so I tried to extract the relevant code here:

[code]
finalSurface = obj.gfx.canvas._specificCanvas.surface.subsurface(
        (obj.gfx.canvasOffset, obj.gfx.size))

if scale != 1.:
    finalSurface = pygame.transform.scale(finalSurface,
            (int(finalSurface.get_width() * scale),
             int(finalSurface.get_height() * scale)))

if obj.gfx.tint != (1.,1.,1.):
    colorKey = finalSurface.get_colorkey()[:3]
    surfaceArray = pygame.surfarray.pixels3d(finalSurface)
    surfaceArray[:,:,:3] = numpy.where(surfaceArray[:,:,:3] != colorKey,
            (surfaceArray[:,:,:3] * obj.gfx.tint).clip(0,255), colorKey)
    del surfaceArray
[/code]

where obj.gfx.canvas._specificCanvas.surfce in the first line contains a normal pygame.surface which was loaded from an image via pygame.image.load()

thanks for looking at this!

//Lorenz