2016-02-11 62 views
6

w moim Pygame grze, aby importować JPEG, używam convert() http://www.pygame.org/docs/ref/surface.html#pygame.Surface.convertPygame ustawić przejrzystość obrazu importować za pomocą convert_alpha()

wtedy, grać z przejrzystości obrazu (ile widzimy koryta image), używam set_alpha() http://www.pygame.org/docs/ref/surface.html#pygame.Surface.set_alpha

jednak, aby zaimportować PNG, które mają tło tranparent używam convert_alpha() http://www.pygame.org/docs/ref/surface.html#pygame.Surface.convert_alpha

ale przy takim sposobie importowania nie mogę grać z ogólną przejrzystością przy użyciu set_alpha(). Każdy inny pomysł, aby dostosować przezroczystość (ile widzimy przez obraz)?

Odpowiedz

6

Kiedy czytasz dokumentację set_alpha można przeczytać: Jeśli format Surface zawiera alfa per pixel, to wartość alfa będą ignorowane.

% W twoim przypadku, z obrazem png, jest to alfabet na piksel. Musisz więc zarządzać alfą "na piksel". Na przykład, można to zrobić (nie najlepsze kod, ale łatwe do zrozumienia Praca z png z nie/tak tylko przejrzystości.):

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

należy zachować ostrożność, to „wolno”, bo uda Ci każdy piksel, który nie ma wartości 0 (przezroczysty z twojego png). Jeśli png ma wiele poziomu przejrzystości, należy zarządzać przejrzystość lepszej formuły, tak:

 r,g,b,old_alpha=img.get_at((x,y)) 
     img.set_at((x,y),(r,g,b,(alpha*old_alpha)/255)) 

I w tym przypadku, nie modyfikować oryginalnego obrazu, ale praca na kopii nie stracić oryginalna alfa.

Mam nadzieję, że to pomoże

===================== EDIT =============== ==== Dodać trochę optymalizacji ponieważ zmierza w komentarzu

z pewnym metodologii buforowania:

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] 

i używać go tak: obraz obciążenie:

image=image_with_alpha("test.png") 

Blit z 60 do alfa:

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

A teraz, to mam nadzieję, że szybko

+0

Miałem czarną ramkę z pierwszą formułą, ale druga działa dobrze :), jednak jest bardzo powolna, moja gra spada do 25 fps ... – n0tis

+0

każdy pomysł na zrobienie jest bardziej zoptymalizowany? – n0tis

+0

Nie wiem, jak działa twoja gra, a optymalizacja takiego kodu zależy od sposobu jego użycia. Ile czasu zmieniła alfa? Jak duże są obrazy? Bez programowania niskopoziomowego możesz użyć "cache" dla danych: Użyjesz więcej pamięci, ale prekomputer alfa dla obrazu pokaże wielką poprawę bez wielu prac. –

0

użyj set_colorkey (color), aby ustawić przezroczysty kolor. na przykład, jeśli masz obraz jabłka, a wszystko oprócz jabłka ma kolor czarny, użyjesz apple.set_colorkey (czarny), a wszystko oprócz jabłka będzie przezroczyste. także, jeśli masz problemy z używaniem obrazu jpg, proponuję zmienić go na png, a następnie robić .convert().

+0

Nie zrozumiałeś mojego pytania. Używam już pliku png. 'convert()' robi czarną ramkę na moim png, więc używam 'convert_alpha' zamiast tego. Kluczowym problemem jest to, że chcę skonfigurować ogólną przejrzystość (ile widzimy przez cały obraz). Zwykle używam 'set_alpha()' dla tego celu. Jednak po zaimportowaniu obrazu za pomocą 'convert_alpha()' tak jak ja, 'set_alpha()' nie działa. Szukam 'set_alpha()' alternatywy – n0tis

1

Ok mam odpowiedź dla Ciebie. Funkcja "convert_alpha()" Pygame nie obsługuje alfa w pikselach. W oparciu o ustawienie docs alfa nie będzie działać. Jednak można obejść to ograniczenie, wykonując następujące czynności. Jeśli załadujesz obraz za pomocą "convert()", a następnie ustawiając alfa, możesz sprawić, że obraz stanie się przezroczysty.Następnie wszystko, co musisz zrobić, to użyć "set_colorkey (kolor tła)", aby wyeliminować obraz tła. Bądź ostrożny z kolorami kluczowymi, ponieważ dowolny kolor na obrazie, który jest ustawiony jako kolor różowy, stanie się przezroczysty. Colorkey nie dba o piksel alfa, więc możesz zmienić alfa obrazu i jednocześnie używać colorkey.

Oto kod ...

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

wrzuciłem ten obraz testowy razem do testowania kodu. Obraz ma przezroczystość wokół jego krawędzi.

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

Mam nadzieję, że to jest to, czego szukasz i nadzieja moja odpowiedź pomogła tutaj.

UWAGA * Możesz zrobić kopię obrazu przed zmianą jego alfa takiego bez ryzyka obrazu o „nadwyżkę” wpływa z poprzednich zastosowań.

2

Najszybszym rozwiązaniem jest prawdopodobnie używać numpy manipulacji tablicy powinno być na tyle szybko, aby uniknąć potrzeby buforowania. Naprawdę powolne w obliczaniu wartości pikseli jest iteracja w Pythonie, natomiast numpy to wszystko w C.

Rozpocznij od odniesienia do kanału alfa obrazu do tablicy numpy. To stworzy blokadę na powierzchni obrazu; pamiętajmy o tym na później. Następnie weź minimalną (w pikselach) oryginalną alfę i tablicę pełną (pozostawiając tablicę jedynych zer i jedynek), pomnóż to (w pikselach) przez pożądaną alfę i skopiuj wynik z powrotem do kanału alfa obrazu (wciąż reprezentowanego przez odniesienie do tej tablicy). Aby można było przesłonić obraz na ekranie, odwołanie do tablicy alfa musi zostać wyczyszczone, zwalniając blokadę na powierzchni obrazu.

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