В настоящее время у меня есть несколько функций, работающих вместе, чтобы изменить размер gif, чтобы он выглядел шире. Проблема в том, что с некоторыми гифками, которые при открытии превращаются в большие куски памяти (то есть у меня есть 2-мегабайтный gif, который при открытии занимает более 256 МБ памяти), эти функции в конечном итоге приводят к тому, что мой процесс завершается из-за нехватки памяти.
В идеале я бы хотел перебирать каждый кадр, вносить изменения и сохранять их все в циклическом анимированном gif. Это работает в большинстве случаев, но я бы хотел, чтобы это работало во всех возможных случаях. В частности, это работает со всеми гифками, которые я использовал в своей среде windows, но проблемы возникают там, где я размещаю процесс, поскольку в этой среде гораздо меньше памяти.
Это гифка, которая ломает вещи: https://media.discordapp.net/attachments/661994364104605705/740933535107514368/source.gif
Это код, который обрабатывает фреймы:
for (i,frame) in enumerate(self.getFrames(im)):
oldWidth, oldHeight = frame.size
(width, height) = (frame.width * 3 * widenMultiple, frame.height // 1) # Provide the target width and height of the image
frame = frame.resize((width, height))
if noCrop == 0 and width >= 2400 and height * 2 < width:
frame = self.centerCrop(frame, width / (3), height)
frameList.append(frame)
Это код, который получает фреймы (не мой, нашел это решение на git ):
def getFrames(self, im):
'''
Iterate the GIF, extracting each frame.
'''
mode = self.analyseImage(im)['mode']
p = im.getpalette()
last_frame = im.convert('RGBA')
try:
while True:
'''
If the GIF uses local colour tables, each frame will have its own palette.
If not, we need to apply the global palette to the new frame.
'''
if not im.getpalette():
im.putpalette(p)
new_frame = Image.new('RGBA', im.size)
'''
Is this file a "partial"-mode GIF where frames update a region of a different size to the entire image?
If so, we need to construct the new frame by pasting it on top of the preceding frames.
'''
if mode == 'partial':
new_frame.paste(last_frame)
new_frame.paste(im, (0, 0), im.convert('RGBA'))
yield new_frame
last_frame = new_frame
im.seek(im.tell() + 1)
except EOFError:
pass
Происходит то, что после нескольких итераций for l oop процесс выводит «убит» при тестировании с этой спецификацией c gif. Я еще не нашел другого примера, но предполагаю, что этот код в целом может потребовать много работы, потому что он, вероятно, считывает одни и те же вещи в память несколько раз, что приведет к очень нездоровому масштабированию эффективности использования пространства.
Я использую imageio для обработки файлов gif, но только для изменения длительности каждого кадра. Этот gif не представляет проблем с imageio, но, что бы он ни стоил, мне пришлось установить memTest=False
при загрузке этого gif, используя imageio.mimread