Hey guys,
I'm trying to implement a "filter" system in my current game (written with python+pygame)- for example that makes the screen become black and white.
I blit all my surfaces to a buffer surface that I blit on the screen, so I thought: "No problem, I'll just access and modify the pixels from the buffer surface". Thing is, the 2 approaches I tried essentially killed the framerate.
The first thing I did was to use the get_at and set_at methods of the Surface class.
self.screenBuffer.lock()
for x in range(0,160):
for y in range(0,144):
color=self.screenBuffer.get_at((x,y))
color.r=color.g=color.b=int((0.1*color.r+0.79*color.g+0.11*color.b)/3)
self.screenBuffer.set_at((x,y), color)
self.screenBuffer.unlock()
This was slow, and the documentation was honest with me:
Getting and setting pixels one at a time is generally too slow to be used in a game or realtime situation. It is better to use methods which operate on many pixels at a time like with the blit, fill and draw methods - or by using surfarray/PixelArray.So I figured I'd use a surface array:
surfArray=pygame.surfarray.pixels3d(self.screenBuffer) #load the pixels from the surface into a surface array
for x in range(0,160):
for y in range(0,144):
color=surfArray[x][y]
color[0]=color[1]=color[2]=int((color[0]*0.59+color[1]*0.3+color[2]*0.11)/3)
surfArray[x][y]=color
self.screenBuffer=pygame.surfarray.make_surface(surfArray) #transform the pixel array back to a surface
Which was even slower.
Anyone has any tips on what I could do to fix that? The documentation seems to indicate that a pixel array could do the trick, but I have the feeling that one cannot read the value of a single pixel's color from the pixel array.