Pygame,使用convert_alpha()导入的图像上设置透明度

时间:2016-02-11 07:15:40

标签: python image pygame png transparency

在我的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()来使用常规透明度。还有其他想法来调整透明度(我们通过图像看到了多少)?

4 个答案:

答案 0 :(得分:6)

当您阅读 set_alpha 的文档时,您可以阅读: 如果Surface格式包含每像素alphas,则此Alpha值将被忽略。

%在您的情况下,使用png图像,它是每像素alpha。因此,您必须管理alpha“每像素”。例如,你可以这样做(不是最好的代码,但很容易理解。只使用没有/是透明度的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))

小心,它“慢”,因为你管理的每个像素都不是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")

Blit with 60 for alpha:

    screen.blit(image.get_img(60),(0,0))

现在,我希望它很快

答案 1 :(得分:2)

最快的解决方案可能是使用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

答案 2 :(得分:1)

好的,我有你的答案。 Pygame" convert_alpha()"函数不支持每像素alpha。根据文档设置,alpha将无效。但是,您可以通过执行以下操作来解决此限制。如果使用" convert()"加载图像,然后设置alpha,则可以使图像变得透明。然后你要做的就是使用" set_colorkey(背景颜色)"消除背景图像。请使用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)

我把这张测试图片放在一起测试代码。图像的边缘周围有透明度。

This is what it looks like blitted onto a green background without the added alpha. The white part was transparent until loaded with ".convert()"

This is the finished look of the image with the whole code applied. The alpha has been stripped and reset, and the colorkey has been set to white because it was the background

我希望这是你正在寻找的,希望我的答案在这里有所帮助。

注意*您可能希望在更改其alpha之前复制图像,而不存在图像溢出"溢出的风险。来自以前的用途的影响。

答案 3 :(得分:0)

使用set_colorkey(color)设置透明色。例如,如果你有一个苹果的图像,除苹果之外的所有东西都是黑色,你会使用apple.set_colorkey(黑色),除了苹果之外的所有东西都是透明的。另外,如果您在使用jpg图像时遇到问题,我建议将其更改为png然后执行.convert()。