I have been going through the documentation and the Pygame functions and classes today, but couldn't find a reasonable way to either create a circular crop of an image or how to use a mask to perform this: assume an empty circle with a line width of 50px, with a single key color, that is supposed to be removed from surface A and then replaced with the contents of the same pixels on surface B (perhaps I'm mixing definitions here between Pygame's Mask and image editors' - such as Photoshop - masks).

I know surfarray can be used for the task (after a list of pixel coordinates is extracted from surface B), but my tests were too slow and ended up hanging the main loop.

Is there a way to achieve the described above through an efficient and quick method, that can be embedded into the main loop of the application without a significant drawback to the overall processing?


Generally speaking it isn't possible to do real-time per-pixel masking with software renderers if performance is a concern. So you need to do the processing offline.

I don't understand the task you are describing - masking is merely the act of selecting certain pixels to avoid operating on, so it sounds more like you are using a mask to perform some sort of colour replacement. If not, and you are literally just looking to render a part of surface B over a part of surface A, then the answer is to process surface B before the main loop starts so that the pixels you don't want to render have alpha values of zero.

If you need to recalculate this masked area every frame, then you're pretty much out of luck with PyGame - it uses a software renderer and doesn't provide the type of modern GPU operations that would make this practical on anything but tiny images.

  • \$\begingroup\$ that's what I had thought - looks like C++ is the way to go, huh? \$\endgroup\$ – planestepper Oct 24 '11 at 10:58
  • 1
    \$\begingroup\$ Even software rendering in C++ is going to struggle compared with doing this in OpenGL or DirectX. Python's not really the problem, it's the software rendering aspect that holds the speed back. But, with a small enough rendering area, software rendering can be fast enough for most operations - it's hard to know whether it would suffice in your case. \$\endgroup\$ – Kylotan Oct 24 '11 at 15:53
  • \$\begingroup\$ my needs are small and simple. What I meant with C++ is that OpenGL needs C++ to have the shaders created, am I right? \$\endgroup\$ – planestepper Oct 24 '11 at 20:10
  • 2
    \$\begingroup\$ No, you're not - OpenGL works the same way whatever language you use it with. It's just that once you use OpenGL you're no longer using PyGame rendering - you have to pretty much bypass that completely. \$\endgroup\$ – Kylotan Oct 24 '11 at 21:52
  • 1
    \$\begingroup\$ Shaders are typically written in a shader-specific language: en.wikipedia.org/wiki/Shader#Programming_shaders \$\endgroup\$ – Kylotan Oct 25 '11 at 12:42

You can do it quite fast with two blits and one copy. If you use colorkey, then:

  1. Have your mask image composed of two colors -- one the "transparent" color of all your other images, and some other color.
  2. Set colorkey on your mask to that other color.
  3. Copy the source image.
  4. Blit your mask on that copy.
  5. Set colorkey on that copy to your "transparent" color.
  6. Blit that copy on your target image.

If you don't use colorkey, you can achieve a similar effect using the alpha channel and the special_flags of the blit method.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.