2012-04-22 20 views
14

ho provato a convertire un GIF per le immagini singole con Python Immagine Biblioteca, ma si traduce in fotogrammi straniPIL - Convertire Frames GIF in JPG

La gif ingresso è:

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

In il mio primo tentativo, ho provato a convertire l'immagine con Image.new in un'immagine RGB , con 255,255,255 come sfondo bianco - come in qualsiasi altro esempio di che ho trovato su internet:

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 

ma si traduce in file di output strani:

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

Il mio secondo tentativo è stato, per convertire il GIF in un RGBA prima, e poi usare la sua maschera di trasparenza, per rendere i pezzi trasparente bianco:

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 

che determini un output del tipo:

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

Il vantaggio rispetto al primo tentativo fu che il primo fotogramma sembra piuttosto buono Ma come si può vedere, il resto è rotto

Cosa dovrei provare dopo?

Edit:

penso che mi è venuto molto più vicino alla soluzione

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

ho dovuto usare la tavolozza della prima immagine per le altre immagini, e fonderlo con la frame precedente (per le animazioni gIF che utilizzano diff-immagini)

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 

Ma i ac tualmente dont know, perché la mia trasparenza è nero, al posto del bianco Anche se modifico la tavolozza (cambiare il canale di trasparenza al bianco) o utilizzare la maschera di trasparenza, lo sfondo è ancora nero

risposta

18

Prima di tutto, JPEG non supporta la trasparenza! Ma non è l'unico problema ..Non appena si passa al fotogramma successivo di GIF le informazioni palette vengono perse (problem witn PIL?), quindi PIL non è in grado di convertire correttamente nel framework RGBA (quindi il primo frame è ok, ma tutti gli altri sono mossi). Quindi la soluzione è aggiungere il palette di nuovo per ogni frame, (che è quello che stavi facendo nel tuo ultimo esempio di codice, ma il tuo problema era che stavi salvando come RGB non RGBA così non avevi nessun canale alpha/trasparenza. Inoltre stavi facendo alcune cose inutili ..). In ogni caso, ecco i .png di trasparenza e con il codice corretto, la speranza la sua di qualche utilità :)

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

Grazie mille! Ho usato incolla con l'ultimo fotogramma, perché alcune gif usano le differenze per ogni fotogramma! – Schinken

+1

Uhm, la sostituzione della tavolozza in questo modo darà risultati errati quando i fotogrammi hanno tavolozze diverse. questa è l'immagine http://www.imagemagick.org/Usage/anim_opt/bunny_bgnd.gif (penso, non sono sicuro se sto copiando e incollando i giusti link). L'altro problema che vedo potrebbe essere legato alle differenze tra le versioni PIL, ma non ottengo lo stesso risultato del tuo (ottengo aree grigie in tutti i frame tranne il primo, dove avrebbe dovuto essere trasparente). Lo stesso accade per un gif come http://www.imagemagick.org/Usage/anim_opt/bunny_bgnd_opttrans.gif. – mmgp

+0

@mmgp - hmm, sì capisco che i fotogrammi con tavolozze diverse potrebbero rappresentare un problema. Sono d'accordo che ottenere risultati diversi potrebbe essere un problema di versione. Sfortunatamente, non ho tempo di guardarlo al momento, se hai una correzione, modifica la mia risposta o aggiungi la tua. Ben fatto. – fraxel

4

Quando si visualizza un'immagine su un visualizzatore di immagini, anche quando la trasparenza è impostata su zero, tende a visualizzare l'immagine come nero. Un modo per essere sicuro che la tua immagine sia veramente trasparente è fonderla su un'altra. Il 'emoticon' dovrebbe essere visto pur non ostacolando l'altro 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 

In teoria, se si apre 'trial.jpg' nel visualizzatore di immagini e il contenuto dell'immagine di partenza è conservato e in cima si trova l'immagine foo quindi saprai per certo se è solo il visualizzatore di immagini e le tue immagini vanno bene ...

+0

.jpeg non supporta la trasparenza :( – fraxel

Problemi correlati