I can't find a way to easily and efficiently transform Surface
s in pygame. By transforming I mean freely reshape an image. For example:
to:
I've tried converting the
Surface
to a numpy array and apply the operation on it, the converting it back to Surface. However, this method seems to be very slow.
Asked
Active
Viewed 232 times
0

PunnyBunny
- 185
- 1
- 10
-
No, the title does not describe the question. You have to be more specific. What transformations do you want to do? Pygame has the [`pygame.transform`](https://www.pygame.org/docs/ref/transform.html) module, [`pygame.surfarray`](https://www.pygame.org/docs/ref/surfarray.html) module and [`pygame.PixelArray`](https://www.pygame.org/docs/ref/pixelarray.html) object. A rect region of a _Surface_ can be get with [`pygame.Surface.subsurface`](https://www.pygame.org/docs/ref/surface.html#pygame.Surface.subsurface). If that doesn't suit your needs, you'll need to go through Numpy and OpenCV (cv2). – Rabbid76 Sep 21 '21 at 15:12
-
Possibly you are searching for [`pygame.mask.Mask`](https://www.pygame.org/docs/ref/mask.html). You can blend (clip) a _Surface_ with a _Mask_. `image.blit(mask.to_surface(), (0, 0), special_flags=pygame.BLEND_RGBA_MULT)` – Rabbid76 Sep 21 '21 at 15:14
-
@Rabbid76 Sorry for the ambiguity. I have clarified in the edit. – PunnyBunny Sep 21 '21 at 23:34
-
The answer is simple: You cannot do this with Pygame. Pygame is just for educational purpose. However you can try to use [`pygame.surfarray.pixels3d`](https://www.pygame.org/docs/ref/surfarray.html#pygame.surfarray.pixels3d) to references the pixel of a _Surface_ directly. It would be nice to see your code. Please read [How to create a Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example). – Rabbid76 Sep 22 '21 at 04:56
1 Answers
0
If you just want to clip an image, you can use the pygame.maks
module.
Convert a pygame.mask.Mask
to a pygame.Surface
with pygame.mask.Mask.to_surface
. Use setsurface
to specify the source image and the unsetcolor
argument to specify the transparent background:
def clip_surface(surf, mask):
return mask.to_surface(setsurface = surf.convert_alpha(), unsetcolor = (0, 0, 0, 0))
Minimal example:
import pygame
def clip_surface(surf, mask):
return mask.to_surface(setsurface = surf.convert_alpha(), unsetcolor = (0, 0, 0, 0))
def checker_image(ts, w, h, c1, c2):
surf = pygame.Surface((w, h))
[pygame.draw.rect(surf, c1 if (x+y) % 2 == 0 else c2, (x*ts, y*ts, ts, ts)) for x in range((w+ts-1)//ts) for y in range((h+ts-1)//ts)]
return surf
pygame.init()
window = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()
background = checker_image(40, *window.get_size(), (129, 128, 128), (96, 96, 96))
image = checker_image(20, 200, 200, (255, 128, 128), (255, 64, 64))
mask_image = pygame.Surface(image.get_size(), pygame.SRCALPHA)
pygame.draw.polygon(mask_image, (255, 255, 255), [(100, 10), (10, 190), (190, 190)])
mask = pygame.mask.from_surface(mask_image)
clipped_image = clip_surface(image, mask)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
window.blit(background, (0, 0))
image_rect = clipped_image.get_rect(center = window.get_rect().center)
pygame.draw.rect(window, (0, 0, 0), image_rect, 3)
window.blit(clipped_image, image_rect)
pygame.display.flip()
pygame.quit()
exit()

Rabbid76
- 202,892
- 27
- 131
- 174