PIL - конвертировать GIF-фреймы в JPG
Я попытался преобразовать gif в отдельные изображения с помощью библиотеки изображений Python,
но это приводит к странным кадрам
Ввод gif:
Исходный образ http://longcat.de/gif_example.gif
В первой попытке я попытался преобразовать изображение с Image.new в
Изображение RGB, с 255 255 255 в виде белого фона - как в любом другом
Например, я нашел в Интернете:
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
но это приводит к появлению странных выходных файлов:
Пример # 1 http://longcat.de/gif_example1.jpg
Моя вторая попытка состояла в том, чтобы сначала преобразовать gif в RGBA, а затем использовать
его прозрачную маску, чтобы сделать прозрачные части белыми:
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
в результате чего получается такой вывод:
Пример # 2 http://longcat.de/gif_example2.jpg
Преимущество перед первой попыткой состояло в том, что первый кадр выглядит довольно неплохо
Но, как вы можете видеть, остальное сломано
Что мне делать дальше?
Edit:
Думаю, я намного ближе к решению
Пример # 3 http://longcat.de/gif_example3.png
Мне пришлось использовать палитру первого изображения для других изображений,
и объединить его с предыдущим фреймом (для анимаций gif, которые используют
Diff-изображения)
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
Но я действительно не знаю, почему моя прозрачность черная, а не белая
Даже если я изменю палитру (измените канал прозрачности на белый)
или использовать маску прозрачности, фон по-прежнему черный
Ответы
Ответ 1
Прежде всего, JPEG
не поддерживает прозрачность! Но это не единственная проблема. Когда вы переходите к следующему кадру GIF
, информация palette
теряется ( проблема witn PIL?) - так что PIL
не может правильно преобразовать в рамки RGBA
(Следовательно, первый кадр окуривает, но все остальные являются отвратительными). Итак, обход - добавить palette
назад для каждого фрейма (это то, что вы делали в своем последнем примере кода, но ваша проблема заключалась в том, что вы сохраняли как RGB
not RGBA
, чтобы вы нет канала альфа/прозрачности. Также вы делали несколько ненужных вещей..). Во всяком случае, вот .png с прозрачностью и исправленным кодом, надеюсь, что это будет полезно:)
![enter image description here]()
![enter image description here]()
![enter image description here]()
![enter image description here]()
![enter image description here]()
![enter image description here]()
![enter image description here]()
![enter image description here]()
![enter image description here]()
![enter 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')
Ответ 2
При просмотре изображения на устройстве просмотра изображений, даже когда прозрачность установлена на ноль, она имеет тенденцию отображать изображение как черное. Один из способов убедиться, что ваш образ действительно прозрачен, - это объединить его над другим. "Волшебник" должен быть замечен, а не препятствовать другому изображению. Попробуйте:
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
Теоретически, если вы открываете "trial.jpg" в средстве просмотра изображений, а содержимое исходного изображения сохраняется, а поверх него находится изображение foo, то вы точно знаете, будет ли это только просмотрщик изображений и ваш изображения в порядке...