[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
Re: [pygame] surfarray.pixels3d(). I'm stumped.
On Sun, 22 Aug 2004, Pete Shinners wrote:
> Jasper Phillips wrote:
> > I'm trying to blur both RGB and alpha using surfarray. I can get it to
> > work with surfarray.array3d() and .array_alpha(), but it's very slow as
> > I end up using Surface.set_at() to combine the results of both methods
> > together.
>
> You'll never want to use the Surface.set_at/get_at functions when doing
> image effects. You'll want to avoid loops like over the whole image,
> like for x in range(width): for y in range(height): it is never going to
> be fast enough.
Thanks for the speedy reply!
Actually, the speed isn't such a big deal, as I only blur images once, not
every frame. It only really matters for improving testing turnaround.
Well, actually it's become academic as I've found a way to wory around
manipulating alpha, but I'm still interested in the general case.
> > exceptions.TypeError: Array can not be safely cast to required type
>
> The "3d" arrays are always Int8 type arrays. Numeric always tries to
> upcast your numbers into regular Int, it is very annoying. With a little
> care or conversion you can get the right types out.
I too was down casting to Numeric.Int8...
> In my old flame example I almost have an convolution filter. Let me see
> if I can do it here in email. This will do a single color channel, so
> you'll apply is separately to R, G, B, and A.
>
> def filter3x3(src, dst, matrix):
> "src and dst must be 2d arrays of the same size"
> w, h = src.shape[0]-2, src.shape[1]-2
> intdst = Numeric.zeros((src.shape[0]-2, src.shape[1]-2))
> for x,y in [(0, 0), (1, 0), (2, 0),
> (0, 1), (1, 1), (2, 1),
> (0, 2), (1, 2), (2, 2)]:
> intdst += src[x:x+w,y:y+w] * matrix[x,y]
> weight = Numeric.sum(Numeric.sum(matrix))
> intdst /= weight
> dst[1:-1,1:-1] = intdst.astype(Numeric.Int8)
>
>
> This doesn't filter the border pixels, but I suppose extra work could be
> done for those too. To call this on the separate color channels you
> would create a pixels3d array for the source and destination, and call
> the function like this
>
> filter3x3(srcarray[::0], dstarray[::0], matrix)
> filter3x3(srcarray[::1], dstarray[::1], matrix)
> filter3x3(srcarray[::2], dstarray[::2], matrix)
> filter3x3(srcalphaarray, dstalphaarray, matrix)
I wasn't able to get this to work. There was a syntax error and an indexing
error, so I tweaked it like so:
def filter3x3(src, dst, matrix):
"src and dst must be 2d arrays of the same size"
w, h = src.shape[0]-2, src.shape[1]-2
intdst = Numeric.zeros((w,h))
for x,y in [(0, 0), (1, 0), (2, 0),
(0, 1), (1, 1), (2, 1),
(0, 2), (1, 2), (2, 2)]:
intdst += src[x:x+w,y:y+h] * matrix[x,y]
weight = Numeric.sum(Numeric.sum(matrix))
intdst /= weight
dst[1:-1,1:-1] = intdst.astype(Numeric.Int8)
def tryPixels3d( surface ):
matrix = Numeric.zeros( (3,3) )
matrix[1,1] = 1
matrix[1,0] = 1
matrix[0,1] = 1
matrix[2,1] = 1
matrix[1,2] = 1
print matrix
srcarray = array3d( surface )
dstarray = pixels3d( surface )
srcalphaarray = array_alpha( surface )
dstalphaarray = pixels_alpha( surface.convert_alpha() )
filter3x3(srcarray[:,:,0], dstarray[:,:,0], matrix)
filter3x3(srcarray[:,:,1], dstarray[:,:,1], matrix)
filter3x3(srcarray[:,:,2], dstarray[:,:,2], matrix)
filter3x3(srcalphaarray, dstalphaarray, matrix)
return surface
I get the same TypeError as with my previous code, on the last line of
filter3x3()...
-Jasper