2012-04-22 8 views
14

Próbowałem przekonwertować gif do pojedynczych obrazów z Python Obrazek Biblioteka ale wynika to w dziwnych klatekPIL - Konwersja ramek GIF do JPG

Gif wejściowy jest:

Source Image http://longcat.de/gif_example.gif

W moja pierwsza próba, próbowałem przekonwertować obraz z Image.new na obraz RGB , z 255,255,255 jako białe tło - jak w każdym innym przykładzie , który znalazłem w Internecie:

def processImage(infile): 

    try: 
     im = Image.open(infile) 
    except IOError: 
     print "Cant load", infile 
     sys.exit(1) 

    i = 0 

    try: 
     while 1: 

      background = Image.new("RGB", im.size, (255, 255, 255)) 
      background.paste(im) 
      background.save('foo'+str(i)+'.jpg', 'JPEG', quality=80) 

      i += 1 
      im.seek(im.tell() + 1) 

    except EOFError: 
     pass # end of sequence 

ale wynika to w dziwnych plików wyjściowych:

Example #1 http://longcat.de/gif_example1.jpg

Moja druga próba była, aby przekształcić gif w RGBA pierwszy, a następnie użyj maskę przezroczystości, aby przezroczyste kawałki białego:

def processImage(infile): 

    try: 
     im = Image.open(infile) 
    except IOError: 
     print "Cant load", infile 
     sys.exit(1) 

    i = 0 

    try: 
     while 1: 

      im2 = im.convert('RGBA') 
      im2.load() 

      background = Image.new("RGB", im2.size, (255, 255, 255)) 
      background.paste(im2, mask = im2.split()[3]) 
      background.save('foo'+str(i)+'.jpg', 'JPEG', quality=80) 

      i += 1 
      im.seek(im.tell() + 1) 

    except EOFError: 
     pass # end of sequence 

co skutkuje wyjściem jak ten:

Example #2 http://longcat.de/gif_example2.jpg

przewagę nad pierwszym razem było to, że pierwsza klatka wygląda całkiem nieźle Ale jak widać, reszta jest podzielona

Co należy próbować dalej?

Edit:

Myślę, że przyszedł dużo bliżej rozwiązania

Example #3 http://longcat.de/gif_example3.png

musiałem użyć paletę pierwszego obrazu do innych obrazów, i połączyć go z poprzednia ramka (dla animacji gif, które wykorzystują diff-obrazów)

def processImage(infile): 

    try: 
     im = Image.open(infile) 
    except IOError: 
     print "Cant load", infile 
     sys.exit(1) 

    i = 0 

    size  = im.size 
    lastframe = im.convert('RGBA') 
    mypalette = im.getpalette() 

    try: 
     while 1: 

      im2 = im.copy() 
      im2.putpalette(mypalette) 

      background = Image.new("RGB", size, (255,255,255)) 

      background.paste(lastframe) 
      background.paste(im2) 
      background.save('foo'+str(i)+'.png', 'PNG', quality=80) 

      lastframe = background 

      i += 1 
      im.seek(im.tell() + 1) 

    except EOFError: 
     pass # end of sequence 

Ale ac nie wiem, dlaczego moja przezroczystość jest czarna, a nie biała Nawet jeśli zmienię paletę (zmienić kanał przezroczystości na biały) lub użyj maski przezroczystości, tło jest nadal czarne

Odpowiedz

18

Po pierwsze, JPEG nie obsługuje przezroczystości! Ale to nie jedyny problem ...Po przejściu do następnej klatki z GIF utracono informacje (problem witn PIL?) - więc PIL nie jest w stanie poprawnie przekonwertować do szkieletu RGBA (stąd pierwsza klatka jest okish, ale wszystkie pozostałe są paskudne). Tak więc obejściem jest dodanie z powrotem do każdej klatki numeru palette (co robiłeś w swoim ostatnim przykładzie kodu, ale kłopot polegał na tym, że zapisałeś jako RGB, a nie RGBA, więc nie masz kanału alfa/przezroczystości. Poza tym robiłeś kilka niepotrzebnych rzeczy ...). Tak czy inaczej, oto .png jest z przejrzystości i skorygowanego kodu, mamy nadzieję, że pewnego użytku :)

enter image description hereenter image description hereenter image description hereenter image description hereenter image description hereenter image description hereenter image description hereenter image description hereenter image description hereenter image description here

import Image 
import sys 

def processImage(infile): 
    try: 
     im = Image.open(infile) 
    except IOError: 
     print "Cant load", infile 
     sys.exit(1) 
    i = 0 
    mypalette = im.getpalette() 

    try: 
     while 1: 
      im.putpalette(mypalette) 
      new_im = Image.new("RGBA", im.size) 
      new_im.paste(im) 
      new_im.save('foo'+str(i)+'.png') 

      i += 1 
      im.seek(im.tell() + 1) 

    except EOFError: 
     pass # end of sequence 

processImage('gif_example.gif') 
+0

Dziękuję bardzo! Używam pasty z ostatnią ramką, ponieważ niektóre gify używają różnic dla każdej klatki! – Schinken

+1

Uhm, zastąpienie palety daje niepoprawne wyniki, gdy ramki mają różne palety. to jest obraz http://www.imagemagick.org/Usage/anim_opt/bunny_bgnd.gif (Myślę, że nie jestem pewien, czy kopiuję i wkleja odpowiednie linki). Drugi problem, który widzę, może być związany z różnicami między wersjami PIL, ale nie otrzymuję takich samych rezultatów jak twoje (otrzymuję szare obszary we wszystkich ramkach z wyjątkiem pierwszego, gdzie powinien być przezroczysty). To samo dzieje się z gifem takim jak http://www.imagemagick.org/Usage/anim_opt/bunny_bgnd_opttrans.gif. – mmgp

+0

@mmgp - hmm, tak, widzę, że ramki z różnymi paletami mogą stanowić problem. Zgadzam się, że uzyskanie różnych wyników może być problemem związanym z wersją. Niestety, nie mam na to czasu, jeśli masz jakąś poprawkę, edytuj moją odpowiedź lub dodaj własną. niezłe. – fraxel

4

Podczas wyświetlania obrazu na przeglądarkę obrazów, nawet gdy przezroczystość jest ustawiona na zero, ma tendencję do wyświetlania obrazu jako czarnego. Jednym ze sposobów upewnienia się, że twój obraz jest naprawdę przejrzysty, jest połączenie go z innym. W „emotikon” powinno być postrzegane jednocześnie nie blokując inne image.Try:

background = Image.open('someimage.jpg') #an existing image 
foreground = Image.open('foo.jpg') #one of the above images 
background.paste(foreground, (0,0), foreground) 
background.save('trial.jpg') #the composite image 

Teoretycznie, jeśli otworzysz „trial.jpg” w przeglądarce zdjęć i treści początkowego obrazu jest zachowana, a na szczycie to jest foo obraz, wtedy będziesz wiedzieć na pewno, czy to tylko przeglądarka obrazów i twoje zdjęcia są w porządku ...

+0

.jpeg nie obsługuje przezroczystości :( – fraxel