Pygame,在使用 convert_alpha() 导入的图像上设置透明度
Pygame, set transparency on an image imported using convert_alpha()
在我的 pygame 游戏中,要导入 jpeg 图片,我使用 convert()
http://www.pygame.org/docs/ref/surface.html#pygame.Surface.convert
然后,为了调整图像透明度(通过图像我们可以看到多少),我使用 set_alpha()
http://www.pygame.org/docs/ref/surface.html#pygame.Surface.set_alpha
但是,要导入具有透明背景的 png 图像,我使用 convert_alpha()
http://www.pygame.org/docs/ref/surface.html#pygame.Surface.convert_alpha
但是通过这种导入方式,我无法使用 set_alpha()
来玩一般透明度。任何其他调整透明度的想法(我们从图像中看到多少)?
使用set_colorkey(颜色)设置透明色。例如,如果你有一个苹果的图像,除了苹果之外的所有东西都是黑色的,你可以使用 apple.set_colorkey(black),这样除了苹果之外的所有东西都是透明的。另外,如果您在使用 jpg 图像时遇到问题,我建议将其更改为 png,然后执行 .convert()。
当您阅读 set_alpha 的文档时,您可以阅读以下内容:
如果 Surface 格式包含每像素 alpha,则此 alpha 值将被忽略。
%在您的例子中,对于 png 图像,它是每像素 alpha。因此,您必须管理 alpha "per pixel"。例如,您可以这样做(不是最好的代码,但很容易理解。使用仅具有 no/yes 透明度的 png):
def change_alpha(img,alpha=255):
width,height=img.get_size()
for x in range(0,width):
for y in range(0,height):
r,g,b,old_alpha=img.get_at((x,y))
if old_alpha>0:
img.set_at((x,y),(r,g,b,alpha))
小心,它是 "slow",因为您管理每个不为 0 的像素(从您的 png 看是透明的)。
如果您的 png 具有多级透明度,您应该使用更好的公式来管理透明度,如下所示:
r,g,b,old_alpha=img.get_at((x,y))
img.set_at((x,y),(r,g,b,(alpha*old_alpha)/255))
在这种情况下,切勿修改原始图像,而是处理副本以永不丢失原始 alpha。
希望对你有所帮助
=====================编辑===================
添加一些优化,因为在评论中询问
使用一些缓存方法:
class image_with_alpha(object):
def __init__(self,name=None):
self.img=None
self.alpha={}
if name:
self.load_image(name)
def load_image(self,name):
self.img=pygame.image.load(name)
self.alpha[255]=self.img
#self.pre_compute_alpha()
def pre_compute_alpha(self):
for alpha in range(0,10):
self.alpha[alpha]=change_alpha(self.img,alpha)
def get_img(self,a=255):
try:
return self.alpha[a]
except:
self.alpha[a]=change_alpha(self.img,a)
return self.alpha[a]
并像这样使用它:
加载图像:
image=image_with_alpha("test.png")
Alpha 为 60 的 Blit:
screen.blit(image.get_img(60),(0,0))
现在,我希望它很快
好的,我有答案给你。 Pygame 的 "convert_alpha()" 函数不支持每像素 alpha。根据文档设置 alpha 将无效。但是,您可以通过执行以下操作来绕过此限制。如果您使用 "convert()" 加载图像,然后设置 alpha,您可以使图像变得透明。然后你所要做的就是使用"set_colorkey(background color)"来消除背景图像。小心使用 colorkey,因为图像中设置为 colorkey 的任何颜色都会变得透明。 colorkey 不关心每个像素的 alpha,因此您可以更改图像的 alpha 并同时使用 colorkey。
这是代码...
#Loading Image
image = pygame.image.load("test.png").convert()
#Setting Alpha
image.set_alpha(some desired alpha)
#Set colorkey To Eliminate Background Color
image.set_colorkey(some background color)
为了测试代码,我把这张测试图拼在一起了。该图像的边缘确实具有透明度。
我希望这就是您要找的,希望我的回答对您有所帮助。
注意* 您可能希望在像这样更改其 alpha 之前制作图像的副本,而不会有图像受到以前使用的 "spillover" 影响的风险。
最快的解决方案可能是使用 numpy
数组操作,它应该足够快以避免缓存的需要。以像素方式计算 alpha 值真正慢的是在 Python 中迭代,而 numpy
在 C 中全部完成。
首先将图像的 alpha 通道引用到 numpy
数组中。这将在图像表面上创建一个锁;让我们记住这一点以备后用。然后取原始 alpha 的最小值(按像素)和一个全为 1 的数组(这将为您留下一个只有 1 和 0 的数组),将其(按像素)乘以您想要的 alpha,然后将结果复制回来到图像的 alpha 通道(仍然由该数组引用表示)。在将图像 blit 到屏幕之前,必须清除对 alpha 数组的数组引用,从而释放对图像表面的锁定。
def change_alpha(img, alpha=255):
chan = pygame.surfarray.pixels_alpha(img)
chan2 = numpy.minimum(chan, numpy.ones(chan.shape, dtype=chan.dtype)) * alpha
numpy.copyto(chan, chan2)
del chan
在我的 pygame 游戏中,要导入 jpeg 图片,我使用 convert()
http://www.pygame.org/docs/ref/surface.html#pygame.Surface.convert
然后,为了调整图像透明度(通过图像我们可以看到多少),我使用 set_alpha()
http://www.pygame.org/docs/ref/surface.html#pygame.Surface.set_alpha
但是,要导入具有透明背景的 png 图像,我使用 convert_alpha()
http://www.pygame.org/docs/ref/surface.html#pygame.Surface.convert_alpha
但是通过这种导入方式,我无法使用 set_alpha()
来玩一般透明度。任何其他调整透明度的想法(我们从图像中看到多少)?
使用set_colorkey(颜色)设置透明色。例如,如果你有一个苹果的图像,除了苹果之外的所有东西都是黑色的,你可以使用 apple.set_colorkey(black),这样除了苹果之外的所有东西都是透明的。另外,如果您在使用 jpg 图像时遇到问题,我建议将其更改为 png,然后执行 .convert()。
当您阅读 set_alpha 的文档时,您可以阅读以下内容: 如果 Surface 格式包含每像素 alpha,则此 alpha 值将被忽略。
%在您的例子中,对于 png 图像,它是每像素 alpha。因此,您必须管理 alpha "per pixel"。例如,您可以这样做(不是最好的代码,但很容易理解。使用仅具有 no/yes 透明度的 png):
def change_alpha(img,alpha=255):
width,height=img.get_size()
for x in range(0,width):
for y in range(0,height):
r,g,b,old_alpha=img.get_at((x,y))
if old_alpha>0:
img.set_at((x,y),(r,g,b,alpha))
小心,它是 "slow",因为您管理每个不为 0 的像素(从您的 png 看是透明的)。 如果您的 png 具有多级透明度,您应该使用更好的公式来管理透明度,如下所示:
r,g,b,old_alpha=img.get_at((x,y))
img.set_at((x,y),(r,g,b,(alpha*old_alpha)/255))
在这种情况下,切勿修改原始图像,而是处理副本以永不丢失原始 alpha。
希望对你有所帮助
=====================编辑=================== 添加一些优化,因为在评论中询问
使用一些缓存方法:
class image_with_alpha(object):
def __init__(self,name=None):
self.img=None
self.alpha={}
if name:
self.load_image(name)
def load_image(self,name):
self.img=pygame.image.load(name)
self.alpha[255]=self.img
#self.pre_compute_alpha()
def pre_compute_alpha(self):
for alpha in range(0,10):
self.alpha[alpha]=change_alpha(self.img,alpha)
def get_img(self,a=255):
try:
return self.alpha[a]
except:
self.alpha[a]=change_alpha(self.img,a)
return self.alpha[a]
并像这样使用它: 加载图像:
image=image_with_alpha("test.png")
Alpha 为 60 的 Blit:
screen.blit(image.get_img(60),(0,0))
现在,我希望它很快
好的,我有答案给你。 Pygame 的 "convert_alpha()" 函数不支持每像素 alpha。根据文档设置 alpha 将无效。但是,您可以通过执行以下操作来绕过此限制。如果您使用 "convert()" 加载图像,然后设置 alpha,您可以使图像变得透明。然后你所要做的就是使用"set_colorkey(background color)"来消除背景图像。小心使用 colorkey,因为图像中设置为 colorkey 的任何颜色都会变得透明。 colorkey 不关心每个像素的 alpha,因此您可以更改图像的 alpha 并同时使用 colorkey。
这是代码...
#Loading Image
image = pygame.image.load("test.png").convert()
#Setting Alpha
image.set_alpha(some desired alpha)
#Set colorkey To Eliminate Background Color
image.set_colorkey(some background color)
为了测试代码,我把这张测试图拼在一起了。该图像的边缘确实具有透明度。
我希望这就是您要找的,希望我的回答对您有所帮助。
注意* 您可能希望在像这样更改其 alpha 之前制作图像的副本,而不会有图像受到以前使用的 "spillover" 影响的风险。
最快的解决方案可能是使用 numpy
数组操作,它应该足够快以避免缓存的需要。以像素方式计算 alpha 值真正慢的是在 Python 中迭代,而 numpy
在 C 中全部完成。
首先将图像的 alpha 通道引用到 numpy
数组中。这将在图像表面上创建一个锁;让我们记住这一点以备后用。然后取原始 alpha 的最小值(按像素)和一个全为 1 的数组(这将为您留下一个只有 1 和 0 的数组),将其(按像素)乘以您想要的 alpha,然后将结果复制回来到图像的 alpha 通道(仍然由该数组引用表示)。在将图像 blit 到屏幕之前,必须清除对 alpha 数组的数组引用,从而释放对图像表面的锁定。
def change_alpha(img, alpha=255):
chan = pygame.surfarray.pixels_alpha(img)
chan2 = numpy.minimum(chan, numpy.ones(chan.shape, dtype=chan.dtype)) * alpha
numpy.copyto(chan, chan2)
del chan