鱼C论坛

 找回密码
 立即注册
查看: 1934|回复: 13

pygame.translate.rotate()

[复制链接]
发表于 2023-6-15 19:26:25 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
Python 的帮助文档提到,

Snipaste_2023-06-15_19-10-58.png

rotate(...)
    rotate(surface, angle) -> Surface
    rotate an image

旋转一个图片

但是在实际使用 rotate() 时就有留白问题。比如我这么一张图


                               
登录/注册后可看大图


rotate 45° 后就会变成


                               
登录/注册后可看大图


再次 rotate 45


                               
登录/注册后可看大图


越变越大!怎么解决啊,才能像在Word中操作一样的效果?

df.gif
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-6-15 19:29:43 | 显示全部楼层
在 Pygame 中,当你旋转一个图片,会有一个所谓的"边界矩形"(bounding rectangle),该矩形围绕着旋转后的图片。因此,每次你旋转图片时,这个边界矩形都可能会变大以适应旋转后的图像,即使旋转的图像本身的大小并没有变化。这就是为什么在连续旋转图片时,图像的尺寸会变大。

要解决这个问题,你需要在旋转之前先裁剪原始图像的边界矩形,以保持图像的大小不变。这可以通过将源图像剪裁到只包含非透明像素来实现。然后,你可以在旋转后再次剪裁图像,以移除任何新添加的空白区域。

下面是一种可能的解决方法:
def trim(image):
    bg = pygame.Surface(image.get_size())
    bg = bg.convert()
    bg.fill((0,0,0))

    left = image.get_width()
    right = 0
    top = image.get_height()
    bottom = 0

    image.set_colorkey((0,0,0))
    for x in range(image.get_width()):
        for y in range(image.get_height()):
            if image.get_at((x, y)) != (0, 0, 0, 0):
                left = min(x, left)
                right = max(x, right)
                top = min(y, top)
                bottom = max(y, bottom)

    width = right - left + 1
    height = bottom - top + 1

    return image.subsurface(pygame.Rect(left, top, width, height))

def rotate(image, angle):
    return pygame.transform.rotate(trim(image), angle)

这里, trim() 函数通过移除所有的透明像素来剪裁一个图像, rotate() 函数则是先剪裁图像,然后再旋转。

需要注意的是,这种方法可能会消耗大量的处理器时间,特别是对于大图片和高帧率动画。一个可能的改进是,不要每帧都旋转图像,而是在开始时预计算一个旋转的图像序列,然后在运行时使用这些预计算的图像。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-15 19:31:13 | 显示全部楼层
isdkz 发表于 2023-6-15 19:29
在 Pygame 中,当你旋转一个图片,会有一个所谓的"边界矩形"(bounding rectangle),该矩形围绕着旋转后的 ...


bg = bg.convert()
的作用是什么?我玩pygame从没用过,而且去掉也没影响
image.set_colorkey((0,0,0))
又是啥意思?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-6-15 19:33:59 | 显示全部楼层

让我们一一来解释这两个函数的含义:

1.  bg = bg.convert()

convert()  是一个非常重要的 Pygame 函数,它会将图像数据转换成一个与显示表面(display surface)格式兼容的新格式。这可以显著提高图像绘制的速度。如果你没有使用  convert() ,那么每次图像被绘制时,Pygame 都必须在内部将其转换成一个可以在屏幕上绘制的格式,这会降低性能。不过,如果你在某些情况下不使用  convert() ,你可能也不会看到明显的性能差异,特别是在处理小图像或者不需要频繁绘制的情况下。

2.  image.set_colorkey((0,0,0))

set_colorkey()  是用于设置透明色的函数。你可以为图像选择一个颜色,使其在图像上绘制时变为透明。在这个例子中,颜色 (0,0,0)(即黑色)被设置为了透明色。这意味着在后续的代码中,所有黑色的像素(具有 RGB 值 (0,0,0))都会被视为透明的,不会被绘制。

这两个函数在很多情况下都很有用,但如果你的代码也可以在没有它们的情况下正常工作,那就可以不用它们。这完全取决于你的具体需求和你正在处理的特定图像。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-15 19:42:05 | 显示全部楼层
isdkz 发表于 2023-6-15 19:33
让我们一一来解释这两个函数的含义:

1.  bg = bg.convert()

那么什么情况需要使用 bg = bg.convert()
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-6-15 19:44:21 | 显示全部楼层
歌者文明清理员 发表于 2023-6-15 19:42
那么什么情况需要使用 bg = bg.convert() 呢

bg = bg.convert()  主要用于提高渲染效率,它会将 Surface 对象的像素格式转换为与屏幕的像素格式一致。通常有以下几种情况可能需要使用  convert() :

1. 大型图片和/或频繁绘制的情况:对于大型图片或在每个游戏循环中都需要绘制的图片,使用  convert()  可以显著提高渲染速度,因为每次绘制时都不需要再进行额外的像素格式转换。

2. 从外部源加载图片:当你从文件或网络加载图片时,加载进来的图像数据可能与显示设备的像素格式不一致。在这种情况下,使用  convert()  函数会使绘制更加高效。

3. 修改图片数据:如果你需要直接修改图像数据(例如,通过  pygame.Surface  对象的  get_at()  或  set_at()  方法),则最好先将其转换为像素数据的原始格式。这样可以避免在读取或写入像素时进行额外的格式转换。

总的来说, convert()  不是必须的,但在处理大型图像或需要频繁更新的图像时,它可以帮助提高 Pygame 的绘图性能。在一些低端的硬件或资源受限的环境中,这可能会有显著的影响。然而,在许多情况下,你可能不会注意到有或没有  convert()  的区别,特别是对于小型图像或较少更新的图像。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-15 19:45:44 | 显示全部楼层
isdkz 发表于 2023-6-15 19:44
bg = bg.convert()  主要用于提高渲染效率,它会将 Surface 对象的像素格式转换为与屏幕的像素格式一致 ...

那一般在哪里调用,不同地方调用有什么区别吗
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-15 19:53:03 | 显示全部楼层
isdkz 发表于 2023-6-15 19:29
在 Pygame 中,当你旋转一个图片,会有一个所谓的"边界矩形"(bounding rectangle),该矩形围绕着旋转后的 ...


《完美地解决了我的问题》
import pygame
pygame.init()

def trim(image):
    bg = pygame.Surface(image.get_size())
    bg = bg.convert()
    bg.fill((0,0,0))

    left = image.get_width()
    right = 0
    top = image.get_height()
    bottom = 0

    image.set_colorkey((0,0,0))
    for x in range(image.get_width()):
        for y in range(image.get_height()):
            if image.get_at((x, y)) != (0, 0, 0, 0):
                left = min(x, left)
                right = max(x, right)
                top = min(y, top)
                bottom = max(y, bottom)

    width = right - left + 1
    height = bottom - top + 1

    return image.subsurface(pygame.Rect(left, top, width, height))

def rotate(image, angle):
    return pygame.transform.rotate(trim(image), angle)


class Actor(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("fishc.png")
        self.rect = self.image.get_rect()
        self.rect.center = 320, 240

size = width, height = 640, 480
screen = pygame.display.set_mode(size)
fishc = Actor()
running = True
while running:
    screen.fill((118, 215, 234))
    screen.blit(fishc.image, fishc.rect)
    fishc.image = rotate(fishc.image, 2)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
    pygame.display.flip()
pygame.quit()
df.gif
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-6-15 19:56:07 | 显示全部楼层
歌者文明清理员 发表于 2023-6-15 19:45
那一般在哪里调用,不同地方调用有什么区别吗

convert()  函数通常在加载图像后立即调用,以优化图像的内部表示,使其更适合快速绘制。以下是一个典型的用法示例:
image = pygame.image.load("image.png")
image = image.convert()

你可能也会在其他地方看到  convert()  的使用,例如在对图像进行某种处理(如缩放或旋转)后:
image = pygame.transform.scale(image, (100, 100))
image = image.convert()

这可能有助于优化处理后的图像的性能,尤其是当你多次绘制这个处理过的图像时。但是请注意,转换可能会消耗一些时间,所以如果你立即使用处理过的图像,那么在处理后调用  convert()  可能并不会提高性能。

此外,请注意  convert()  方法会删除图像的 alpha 通道(如果有的话)。如果你的图像有 alpha 通道(即它是部分透明的),你应该使用  convert_alpha()  方法而不是  convert() 。

总的来说,最佳的  convert()  调用位置取决于你的具体需求。一般来说,在加载图像后立即调用它是最常见的做法,因为这可以确保图像在首次绘制时就已经被优化。然而,在其他地方调用它可能在某些情况下有用,尤其是当你需要处理大量图像,或者需要多次绘制处理过的图像时。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-15 20:43:47 | 显示全部楼层
isdkz 发表于 2023-6-15 19:56
convert()  函数通常在加载图像后立即调用,以优化图像的内部表示,使其更适合快速绘制。以下是一个典型 ...

8#
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-6-15 20:44:38 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-15 20:49:57 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-15 21:48:08 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-6-16 22:12:22 | 显示全部楼层

8#他说有问题
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-9-22 21:31

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表