PyGameExamplesAndAnswers

StackOverflow            reply.it reply.it

“The first principle is that you must not fool yourself and you are the easiest person to fool.”
Richard P. Feynman


Surface and image

Related Stack Overflow questions:

Surface rectangle

Related Stack Overflow questions:

pygame.Surface.get_rect() returns a rectangle with the size of the Surface object, that always starts at (0, 0) since a Surface object has no position. A Surface is blit at a position on the screen. The position of the rectangle can be specified by a keyword argument. For example, the center of the rectangle can be specified with the keyword argument center. These keyword argument are applied to the attributes of the pygame.Rect before it is returned (see pygame.Rect for a full list of the keyword arguments).

pygame.Surface.get_rect.get_rect() returns a rectangle with the size of the Surface object, but it returns a rectangle that always starts at (0, 0) since a Surface object has no position.
The Surface is placed at a position on the display with the blit function.

You’ve to set the location of the rectangle, either by a keyword argument, e.g:

self.rect = self.image.get_rect(topleft = (self.x, self.y))

or an assignment to a virtual attribute (see pygame.Rect), e.g:

self.rect = self.image.get_rect()
self.rect.topleft = (self.x, self.y)

Surface relativity

Related Stack Overflow questions:

Surface format and performance

Related Stack Overflow questions:

Ensure that the image Surface has the same format as the display Surface. Use convert() (or convert_alpha()) to create a Surface that has the same pixel format. This improves performance when the image is blit on the display, because the formats are compatible and blit does not need to perform an implicit transformation.

screen = pygame.display.set_mode((800, 600))
background = pygame.image.load('background.png').convert()

Note, if the surface has a different format than the display, then blit has to convert the format on the fly in every frame.

Draw an image

Related Stack Overflow questions:

Subsurface and pixel array

Subsurface

Related Stack Overflow questions:

There are 2 possibilities.

The blit method allows to specify a rectangular sub-area of the source _Surface:

[…] An optional area rectangle can be passed as well. This represents a smaller portion of the source Surface to draw. […]

In this way you can blit an area of the source surface directly onto a target:

cropped_region = (x, y, width, height)
traget.blit(source_surf, (posx, posy), cropped_region)

Alternatively, you can define a subsurface that is directly linked to the source surface with the subsurface method:

Returns a new Surface that shares its pixels with its new parent. The new Surface is considered a child of the original. Modifications to either Surface pixels will effect each other.

As soon as a subsurface has been created, it can be used as a normal surface at any time:

cropped_region = (x, y, width, height)
cropped_subsurf = source_surf.subsurface(cropped_region)
traget.blit(cropped_subsurf, (posx, posy))

Pixel array

Related Stack Overflow questions:

Transparent surface and color key

Related Stack Overflow questions:

Make a uniform colored background transparent

Related Stack Overflow questions:

Most likely, your image is not transparent at all. The transparency is stored in the alpha value. Compared to JPG and BMP, the PNG and GIF formats offer an alpha value per pixel. Converting an image to PNG or GIF format does not make an image transparent. You need to paint or download a transparent image.

The pygame documentation notes that:

The returned Surface will contain the same color format, colorkey and alpha transparency as the file it came from. You will often want to call convert() with no arguments, to create a copy that will draw more quickly on the screen.
For alpha transparency, like in .png images, use the convert_alpha() method after loading so that the image has per pixel transparency.

Hence if your image provides per pixel alpha, it is recommended that you call convert_alpha(), but this is not required.

If your image has not transparent pixel, but a uniform colored background, set a transparent color key with set_colorkey()

The color key specifies the color that is treated as transparent. For example, if you have an image with a black background that should be transparent, set a black color key:

my_surface.set_colorkey((0, 0, 0))

Create transparent Surface

Related Stack Overflow questions:

You have 3 possibilities:

You don’t need to change the background color of the image to the background color of the window, but make the background of the image transparent.

Set the transparent color key by pygame.Surface.set_colorkey:

Set the current color key for the Surface. When blitting this Surface onto a destination, any pixels that have the same color as the colorkey will be transparent.

The white artifacts you can see in the picture are caused because the JPG format is a compressed format.
The compression is not lossless. This means the colors around the weapon are not exactly white (255, 255, 255). The color appear to be white for the human eye, but actually the color channels have a value lass than 255, but near to 255.

You can try to correct this manually. Ensure that format of the image has an alpha channel by pygame.Surface.convert_alpha(). Identify all the pixel, which have a red green and blue color channel above a certain threshold (e.g. 230). Change the color channels and the alpha channel of those pixels to (0, 0, 0, 0):

img = pygame.image.load(IMAGE).convert_alpha()

threshold = 230
for x in range(img.get_width()):
    for y in range(img.get_height()):
        color = img.get_at((x, y))
        if color.r > threshold and color.g > threshold and color.b > threshold:
            img.set_at((x, y), (0, 0, 0, 0))

Of course you are in danger to change pixels which you don’t want to change to. If the weapon would have some very “bright” areas, then this areas my become transparent, too.

Note, an issue like this can be avoided by using a different image format like BMP or PNG.
With this formats the pixel can be stored lossless. You can try to “photo shop” the image. Manually change the pixel around the weapon and store the image with a different format.

Negative image

Related Stack Overflow questions:

Floating point

Related Stack Overflow questions:

Load image

Related Stack Overflow questions:

Images are represented by “pygame.Surface” objects. A Surface can be created from an image with pygame.image.load:

my_image_surface = pygame.load.image('my_image.jpg')

However, the pygame documentation notes that:

The returned Surface will contain the same color format, colorkey and alpha transparency as the file it came from. You will often want to call convert() with no arguments, to create a copy that will draw more quickly on the screen.
For alpha transparency, like in .png images, use the convert_alpha() method after loading so that the image has per pixel transparency.

Use the appropriate conversion method for best performance:

image_surface = pygame.load.image('my_image.jpg').convert()
alpha_image_surface = pygame.load.image('my_icon.png').convert_alpha()

A Surface can be drawn on or blended with another Surface using the blit method. The first argument to blit is the Surface that should be drawn. The second argument is either a tuple (x, y) representing the upper left corner or a rectangle. With a rectangle, only the upper left corner of the rectangle is taken into account. It should be mentioned that the window respectively display is also represented by a Surface. Therefore, drawing a Surface in the window is the same as drawing a Surface on a Surface:

window_surface.blit(image_surface, (x, y))
window_surface.blit(image_surface,
    image_surface.get_rect(center = window_surface.get_rect().center))

📁 Minimal example - Load image

What is a good way to draw images using pygame?

📁 Minimal example - Load transparent image

repl.it/@Rabbid76/PyGame-LoadTransparentImage

How do I blit a PNG with some transparency onto a surface in Pygame?

Load multiple images

Related Stack Overflow questions:

Get a list of all the files in the directory (see os) and create a dictionary with the loaded files:

path = 'Desktop/Files/Dungeon Minigame/'
filenames = [f for f in os.listdir(path) if f.endswith('.png')]
images = {}
for name in filenames:
    imagename = os.path.splitext(name)[0] 
    images[imagename] = pygame.image.load(os.path.join(path, name)).convert_alpha()

You can access the images in the dictionary by its name:

screen.blit(images['background'], (0, 0))

Alternatively you can add variables to global namespace, using globals():

path = 'Desktop/Files/Dungeon Minigame/'
filenames = [f for f in os.listdir(path) if f.endswith('.png')]
for name in filenames:
    imagename = os.path.splitext(name)[0] 
    globals()[imagename] =  pygame.image.load(os.path.join(path, name)).convert_alpha()
screen.blit(background, (0, 0))

Image load performance (lagging)

Related Stack Overflow questions:

Load Pillow image

Related Stack Overflow questions:

def pilImageToSurface(pilImage):
    return pygame.image.fromstring(
        pilImage.tobytes(), pilImage.size, pilImage.mode).convert()

📁 Minimal example - Load PIL image to PyGame Surface

Load SVG

Scalable Vector Graphics (SVG)

Since 2.0.2, SDL Image supports SVG (Scalable Vector Graphics) files (see SDL_image 2.0). Therefore, with pygame version 2.0.1, SVG files can be loaded into a pygame.Surface object with pygame.image.load():

surface = pygame.image.load('my.svg')

Before Pygame 2, you had to implement Scalable Vector Graphics loading with other libraries. Below are some ideas on how to do this.

See Surface and image, load SVG

Animate Sprite

Related Stack Overflow questions:

Load Sprite Sheet

Spritesheet.

Related Stack Overflow questions:

📁 Minimal example - Load Sprite Sheet

Load animated GIF

PyGame respectively the pygame.image module can only handle non-animated GIFs.
But on the PyGame homepage is introduced the GIFImage library:

This library adds GIF animation playback to pygame.

Another option is to use a library to load the GIF frame by frame to a list.

For instance use the Pillow library (pip install Pillow).

Write a function, that can convert a PIL image to a pygame.Surface and use the PIL library to load a GIF frame by frame:
(see also Extracting The Frames Of An Animated GIF Using Pillow and PIL and pygame.image)

from PIL import Image, ImageSequence
def pilImageToSurface(pilImage):
    mode, size, data = pilImage.mode, pilImage.size, pilImage.tobytes()
    return pygame.image.fromstring(data, size, mode).convert_alpha()

def loadGIF(filename):
    pilImage = Image.open(filename)
    frames = []
    if pilImage.format == 'GIF' and pilImage.is_animated:
        for frame in ImageSequence.Iterator(pilImage):
            pygameImage = pilImageToSurface(frame.convert('RGBA'))
            frames.append(pygameImage)
    else:
        frames.append(pilImageToSurface(pilImage))
    return frames

Or use OpenCV/opencv-python library and VideoCapture

Write a function, that can convert a cv2 pygame.image image to a pygame.Surface a nd use the library to load a GIF frame by frame:
(see also Read GIF files in Python and How do I convert an OpenCV (cv2) image (BGR and BGRA) to a pygame.Surface object)

import cv2
def cv2ImageToSurface(cv2Image):
    size = cv2Image.shape[1::-1]
    format = 'RGBA' if cv2Image.shape[2] == 4 else 'RGB'
    cv2Image[:, :, [0, 2]] = cv2Image[:, :, [2, 0]]
    surface = pygame.image.frombuffer(cv2Image.tostring(), size, format)
    return surface.convert_alpha() if format == 'RGBA' else surface.convert()

def loadGIF(filename):
    gif = cv2.VideoCapture(filename)
    frames = []
    while True:
        ret, cv2Image = gif.read()
        if not ret:
            break
        pygameImage = cv2ImageToSurface(cv2Image)
        frames.append(pygameImage)
    return frames

📁 Minimal example - Load animated GIF PyGame Surface list using cv2

📁 Minimal example - Load animated GIF PyGame Surface list using PLI

How can I load an animated GIF and get all of the individual frames in PyGame?

Store Image (Save image)

Related Stack Overflow questions:

The image format must be one that supports an alpha channel (e.g. PNG):

pygame.image.save(the_img, "my_image.png")

If you have a Surface with a color key (set_colorkey), you have to change the pixel format of the image including per pixel alphas with pygame.Surface.convert_alpha:

pygame.image.save(the_img.convert_alpha(), the_name)

If you have a surface with a global alpha value (set_alpha), you need to blit the Surface on a transparent Surface (pygame.SRCALPHA) of the same size and store that transparent Surface (this also works for a Surface with a color key):

the_img.set_colorkey((0, 0, 0))
the_img_alpha = pygame.Surface(the_img.get_size(), pygame.SRCALPHA)
the_img_alpha.blit(the_img, (0, 0))

pygame.image.save(the_img_alpha, the_name)

📁 Minimal example - Scroll

Surface lock

Related Stack Overflow questions:

Transformation

Related Stack Overflow questions:

Flip

Related Stack Overflow questions:

Scale

See Scale and zoom

Rotate

See Rotate surface

Scroll

Related Stack Overflow questions:

Blur