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

Re: [pygame] surfarray.pixels3d(). I'm stumped.



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.

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.

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)