如何在Pygame中将图像缩放到屏幕尺寸?

50

我想知道如何在pygame项目中按照屏幕分辨率缩放图像大小。例如,暂时先假设使用窗口显示模式;全屏显示应该是相同的:

  • 我有一张1600x900的背景图片,当然可以在1600x900的窗口中原生显示。

  • 1280x720的窗口中,我可以将此图像的矩形缩放到1280x720

  • 但是,如果我需要添加一个300x300 px,以x,y 1440,860(示例尺寸)的大小放置于原始的1600x900背景上会发生什么呢?当然,在1600x900情况下,我当然可以原生使用该图像,但对于较小/较大的窗口尺寸呢?

如何将图像缩放到窗口大小,并相应地定位它们?我想必须有一个真正简单的自动化方法,但现在我无法弄清楚。

5个回答

99

您可以使用pygame.transform.scale来缩放图像:

import pygame
picture = pygame.image.load(filename)
picture = pygame.transform.scale(picture, (1280, 720))

您可以使用以下代码获取picture的边界矩形:

rect = picture.get_rect()

移动图片

rect = rect.move((x, y))
screen.blit(picture, rect)

其中screen类似于以下设置:

screen = pygame.display.set_mode((1600, 900))

为了让您的小部件能够适应各种屏幕尺寸,您可以使显示器具有可调整大小的功能


import os
import pygame
from pygame.locals import *

pygame.init()
screen = pygame.display.set_mode((500, 500), HWSURFACE | DOUBLEBUF | RESIZABLE)
pic = pygame.image.load("image.png")
screen.blit(pygame.transform.scale(pic, (500, 500)), (0, 0))
pygame.display.flip()
while True:
    pygame.event.pump()
    event = pygame.event.wait()
    if event.type == QUIT:
        pygame.display.quit()
    elif event.type == VIDEORESIZE:
        screen = pygame.display.set_mode(
            event.dict['size'], HWSURFACE | DOUBLEBUF | RESIZABLE)
        screen.blit(pygame.transform.scale(pic, event.dict['size']), (0, 0))
        pygame.display.flip()

1
好的,我明白了。但是如果背景图像从1600x900缩放到1280x720,而按钮的图像从300x300缩放到相对于1280x720-1600x900的某个尺寸,那么我该如何计算出在较小的窗口中按钮应该放置在哪里呢?因为显然,在1280x720显示器上,向下600个像素比在1280x900屏幕上更多,相对而言。 - Ilmiont
1
你是指如何调整不同宽高比的尺寸吗?您需要计算出宽高比并将每个尺寸值乘以其因子。 - cprn

9
如果将 1600x900 缩放至 1280x720,则会得到
scale_x = 1280.0/1600
scale_y = 720.0/900

然后您可以使用它来查找按钮大小和位置。
button_width  = 300 * scale_x
button_height = 300 * scale_y

button_x = 1440 * scale_x
button_y = 860  * scale_y

如果你将 1280x720 的比例缩放到 1600x900,则会得到:
scale_x = 1600.0/1280
scale_y = 900.0/720

其余部分相同。


我将值添加.0以使其成为float - 否则scale_xscale_y将被四舍五入为integer - 在此示例中为0(零)(Python 2.x)


3
不使用pygame.transform.scale有什么理由吗? - rain_

4

使用pygame.transform.scale()或者smoothscale函数,可以轻松将背景缩放到窗口大小。例如:

import pygame

pygame.init()
window = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()

background = pygame.image.load('sky.png').convert()
background = pygame.transform.smoothscale(background, window.get_size())

run = True
while run:
    clock.tick(100)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    window.blit(background, (0, 0))
    pygame.display.flip()

pygame.quit()
exit()

然而,这并没有考虑到背景的宽高比。为使窗口符合背景,需要比较宽高比并将图像按最小比例进行缩放。
以下函数按比例缩放图像以适应所需大小,但保留了其宽高比。该函数返回缩放后的图像和指示缩放后图像在区域中心位置的矩形:
def transformScaleKeepRatio(image, size):
    iwidth, iheight = image.get_size()
    scale = min(size[0] / iwidth, size[1] / iheight)
    new_size = (round(iwidth * scale), round(iheight * scale))
    scaled_image = pygame.transform.smoothscale(image, new_size) 
    image_rect = scaled_image.get_rect(center = (size[0] // 2, size[1] // 2))
    return scaled_image, image_rect

如果你想要填充整个窗口作为背景,并保持纵横比,但是裁剪掉背景的两侧,只需将 min 替换为 maxscale = max(size[0] / iwidth, size[1] / iheight)
scale = max(size[0] / iwidth, size[1] / iheight)

最简示例

import pygame

def transformScaleKeepRatio(image, size):
    iwidth, iheight = image.get_size()
    scale = min(size[0] / iwidth, size[1] / iheight)
    #scale = max(size[0] / iwidth, size[1] / iheight)
    new_size = (round(iwidth * scale), round(iheight * scale))
    scaled_image = pygame.transform.smoothscale(image, new_size) 
    image_rect = scaled_image.get_rect(center = (size[0] // 2, size[1] // 2))
    return scaled_image, image_rect

pygame.init()
window = pygame.display.set_mode((300, 300), pygame.RESIZABLE)
clock = pygame.time.Clock()

background = pygame.image.load('parrot.png').convert_alpha()
scaled_bg, bg_rect = transformScaleKeepRatio(background, window.get_size())

run = True
while run == True:
    clock.tick(100)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

        elif event.type == pygame.VIDEORESIZE:
            window = pygame.display.set_mode(event.size, pygame.RESIZABLE)
            scaled_bg, bg_rect = transformScaleKeepRatio(background, window.get_size())

    window.fill((127, 127, 127))
    window.blit(scaled_bg, bg_rect)
    pygame.display.flip()

pygame.quit()
exit()

2

我不知道你是不是指的这个,但以下是如何将图像按照最大可能的尺寸缩放到屏幕大小,同时保持图像宽高比的方法。

row = pygame.image.load(f"{image}")
x, y = row.get_size()
rx = 1000 / x
ry = 600 / y
print(rx)
print(ry)
ratio = rx if rx < ry else ry
row = pygame.transform.scale(row, (int(x*rx), int(y*rx)))

0
以下是一份配方,可以将图片缩放到屏幕大小,使其保持纵横比,并始终不超出屏幕范围。
screen_resolution = (1920, 1080)
image_path = '/path/to/image.png'
center_image = True
image = pygame.image.load(image_path)

screen_w, screen_h = screen_resolution
image_w, image_h = image.get_size()

screen_aspect_ratio = screen_w / screen_h
photo_aspect_ratio = image_w / image_h

if screen_aspect_ratio < photo_aspect_ratio:  # Width is binding
    new_image_w = screen_w
    new_image_h = int(new_image_w / photo_aspect_ratio)
    image = pygame.transform.scale(image, (new_image_w, new_image_h))
    image_x = 0
    image_y = (screen_h - new_image_h) // 2 if center_image else 0

elif screen_aspect_ratio > photo_aspect_ratio:  # Height is binding
    new_image_h = screen_h
    new_image_w = int(new_image_h * photo_aspect_ratio)
    image = pygame.transform.scale(image, (new_image_w, new_image_h))
    image_x = (screen_w - new_image_w) // 2 if center_image else 0
    image_y = 0

else:  # Images have the same aspect ratio
    image = pygame.transform.scale(image, (screen_w, screen_h))
    image_x = 0
    image_y = 0

display.blit(image, (image_x, image_y))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接