2012-04-22 21 views
14

me trató de convertir un gif para imágenes individuales con Python biblioteca de imágenes, pero da lugar a tramas extrañasPIL - Convertir Marcos GIF a JPG

El GIF de entrada es:

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

En mi primer intento, traté de convertir la imagen con Image.new en una imagen RGB , con 255,255,255 como fondo blanco, como en cualquier otro ejemplo de que he encontrado en 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 

pero resulta en archivos de salida extraños:

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

Mi segundo intento fue, para convertir el gif en una RGBA primero, y luego usar su máscara de transparencia, para hacer las piezas transparentes blanco:

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 

que se traduce en una salida como esta:

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

La ventaja sobre el primer intento fue, que el primer cuadro se ve muy bien Pero como se puede ver, el resto se divide

¿Qué debería probar la próxima?

Editar:

Creo que me encontré mucho más cerca de la solución

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

tuve que usar la paleta de la primera imagen para las otras imágenes, y fusionarla con la fotograma anterior (para animaciones gif que utilizan diff-imágenes)

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 

Pero i ac tualmente dont know, por qué mi transparencia es negro, en lugar de blanco Incluso si modifico la paleta (cambiar el canal de transparencia a blanco) o uso la máscara de transparencia, el fondo sigue siendo negro

Respuesta

18

En primer lugar, JPEG no es compatible con la transparencia. Pero ese no es el único problema ...A medida que avanza al siguiente fotograma de GIF, se pierde la información palette (problem witn PIL?) - por lo que PIL no puede convertirse correctamente al marco RGBA (por lo tanto, el primer fotograma es okish, pero todos los demás son complicados). Entonces la solución es agregar el palette para cada fotograma (que es lo que estaba haciendo en su último ejemplo de código, pero su problema fue que estaba guardando como RGB y no como RGBA, por lo que no tenía canal alfa/transparencia. También estabas haciendo algunas cosas innecesarias ...). De todos modos, aquí están las del png con la transparencia y el código corregido, esperan su de alguna utilidad :)

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

Muchas gracias! Uso pasta con el último fotograma, porque algunos gifs usan diffs para cada fotograma! – Schinken

+1

Uhm, reemplazar la paleta de esa manera dará resultados incorrectos cuando los marcos tengan diferentes paletas. Un ejemplo de esa es la imagen http://www.imagemagick.org/Usage/anim_opt/bunny_bgnd.gif (creo que no estoy seguro si estoy copiando y pegando los enlaces correctos). El otro problema que veo podría estar relacionado con las diferencias entre las versiones de PIL, pero no obtengo el mismo resultado que el tuyo (obtengo áreas grises en todos los marcos excepto en el primero, donde debería haber sido transparente). Lo mismo ocurre con un gif como http://www.imagemagick.org/Usage/anim_opt/bunny_bgnd_opttrans.gif. – mmgp

+0

@mmgp - hmm, sí Puedo ver que los marcos con diferentes paletas pueden suponer un problema. Estoy de acuerdo en que obtener resultados diferentes podría ser un problema de versión. Desafortunadamente, no tengo tiempo para ver esto en este momento; si tienes una solución, edita mi respuesta o agrega la tuya. Buena esa. – fraxel

4

Cuando vea una imagen en una Visor de imágenes, incluso cuando la transparencia se establece en cero, tiende a mostrar la imagen en negro. Una forma de asegurarse de que su imagen sea realmente transparente es fusionarla sobre otra. El 'emoticono' debe ser visto mientras no obstruir la otra 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 

En teoría, si se abre 'trial.jpg' en el visor de imágenes y el contenido de la imagen inicial se conserva y en la parte superior de yace la imagen foo, entonces sabrá con certeza si es solo el visor de imágenes y sus imágenes están bien ...

+0

.jpeg no admite la transparencia :( – fraxel