Pygame, установите прозрачность изображения, импортированного с помощью 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(). Любая другая идея настроить прозрачность (сколько мы видим через изображение)?

4 ответов


когда вы читаете документацию для set_alpha вы можете прочитать это : если формат поверхности содержит Альфы на пиксель, то это альфа-значение будет проигнорировано.

%в вашем случае, с изображением png, это Альфы на пиксель. Итак, вы должны управлять Альфой "на пиксель". Например, вы можете сделать это (не лучший код, но его легко понять. Работа с png только с прозрачностью no/yes):

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))

и в этом случае никогда не изменяйте исходное изображение, но работайте над копией, чтобы никогда не потерять свою оригинальную Альфу.

надеюсь, это поможет

===================== изменить =================== Добавьте некоторую оптимизацию, потому что спросите в комментарии

С методология кэширования:

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")

Блит с 60 для Альфы:

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

и теперь, я надеюсь, это быстро


самое быстрое решение, вероятно, использовать numpy Array manipulation, он должен быть достаточно быстрым, чтобы избежать необходимости кэширования. Что действительно медленно в вычислении Альфа-значения по пикселям, это итерация в Python, в то время как numpy все это в с.

начните с ссылки на альфа-канал изображения в numpy массив. Это создаст блокировку на поверхности изображения; давайте вспомним об этом позже. Затем возьмите минимум (по пикселям) вашей исходной Альфы и массива полный единиц (которые оставят вас с массивом только единиц и нулей), умножьте это (по пикселям) на желаемую Альфу и скопируйте результат обратно в альфа-канал изображения (все еще представленный этой ссылкой на массив). Перед тем, как вы сможете стереть изображение на экран, ссылка массива на альфа-массив должна быть очищена, освобождая блокировку на поверхности изображения.

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

Ok у меня есть ответ для вас. Функция "convert_alpha()" Pygame не поддерживает каждый пиксель Альфа. На основе настроек документов alpha не будет иметь никакого эффекта. Однако, вы можете обойти это ограничение следующим образом. Если вы загружаете свое изображение с помощью " convert ()", а затем устанавливаете alpha, вы можете сделать свое изображение прозрачным. Тогда все, что вам нужно сделать, это использовать "set_colorkey(цвет фона)", чтобы устранить фоновое изображение. Будьте carful с colorkey, потому что любой цвет в изображении это установлено как colorkey станет прозрачным. Colorkey не заботится об Альфе на пиксель, поэтому вы можете изменить Альфа изображения и использовать 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)

Я бросил эту тестовую картинку вместе для тестирования кода. Изображение имеет прозрачность по краям.

это похоже блитироваться на зеленом фоне без дополнительных Альфа. Белая часть была прозрачной пока не загрузится ".преобразовать ()"

это готовый вид изображения со всем примененным кодом. Альфа была разделена и сброшена, а colorkey был установлен на белый, потому что это был фон

Я надеюсь, что это то, что вы ищете, и надеялся, что мой ответ помог здесь.

Примечание* Вы можете сделать копию изображения, прежде чем изменить его альфа, как это без риска изображения, имеющего" перелив " влияет от предыдущих применений.


используйте set_colorkey (color) для установки прозрачного цвета. например, если у вас есть изображение яблока, и все, кроме яблока, имеет черный цвет, вы бы использовали apple.set_colorkey (черный), и все, кроме яблока, будет прозрачным. кроме того, если у вас возникли проблемы с использованием jpg-изображения, я бы предложил изменить его на png, а затем сделать .конвертировать.)(