“The first principle is that you must not fool yourself and you are the easiest person to fool.”
Richard P. Feynman
Related Stack Overflow questions:
Related Stack Overflow questions:
How to center an image in the middle of the window in pygame?
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)
Related Stack Overflow questions:
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.
Related Stack Overflow questions:
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))
Related Stack Overflow questions:
Related Stack Overflow questions:
How do I blit a PNG with some transparency onto a surface in Pygame?
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 theconvert_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))
Related Stack Overflow questions:
You have 3 possibilities:
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))
You can enable additional functions when creating a new surface. Set the SRCALPHA
flag to create a surface with an image format that includes a per-pixel alpha. The initial value of the pixels is (0, 0, 0, 0):
my_surface = pygame.Surface((width, height), pygame.SRCALPHA)
Use convert_alpha()
to create a copy of the Surface with an image format that provides alpha per pixel.
However, if you create a new surface and use convert_alpha()
, the alpha channels are initially set to maximum. The initial value of the pixels is (0, 0, 0, 255). You need to fill the entire surface with a transparent color before you can draw anything on it:
my_surface = pygame.Surface((width, height))
my_surface = my_surface.convert_alpha()
my_surface.fill((0, 0, 0, 0))
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.
Related Stack Overflow questions:
Related Stack Overflow questions:
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 theconvert_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
📁 Minimal example - Load transparent image
repl.it/@Rabbid76/PyGame-LoadTransparentImage
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))
Related Stack Overflow questions:
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
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
Related Stack Overflow questions:
Related Stack Overflow questions:
📁 Minimal example - Load Sprite Sheet
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
Related Stack Overflow questions:
Is there any way to convert the screen of a pygame gui into an image somehow?
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)
Related Stack Overflow questions:
Related Stack Overflow questions:
Related Stack Overflow questions:
See Scale and zoom
See Rotate surface
Related Stack Overflow questions: