在 python 中使用 PIL 保存 GIF 会缩小帧

问题描述 投票:0回答:0

我正在使用 Python 创建一个程序,该程序可以使用 Sprite 存储库中的 Sprite 表自动为我制作 Pokemon gif。它结合了动画和它的阴影来创建一个 sprite 表,然后将其切割成帧。这些帧被组装成 GIF,然后在程序中显示在画布内,所以我知道要下载什么。 GIF 在 cavasses 中的外观和功能非常完美,但是当我使用 PIL 并尝试保存 GIF 时,它会做一些奇怪的事情,它会裁剪框架,因此框架的边缘和阴影有时会被移除,就像它不必要地夹在框架周围一样.

正如您在下面的代码中看到的,我尝试了几乎所有我知道的方法。不过,我很可能会遗漏一些东西。

请注意,每个帧在保存之前都是完全相同的大小,即使调整它们的大小,问题仍然存在。当每个帧单独导出时,它会保留其原始大小,只有当它试图将所有帧一起放入 gif 时才会出现问题。

    def download_this(button, download_single_buttons):
        export_directory = config.get('Directory', 'export_directory')
        idx = download_single_buttons.index(button)
        starting_frame_index = idx * num_cols
        canvas_frames = frames[starting_frame_index: starting_frame_index + num_cols]

        canvas_frames = [ImageTk.getimage(f) for f in canvas_frames]

        durations = frame_duration_values[:num_cols]
        loop_value = 0 if loop_check_value.get() else 1

        if loop_value == 0:
            filename = f"{export_directory}\{(this_poke.lower())}-{(animations.lower())}({directions[idx]}).gif"
        else:
            filename = f"{export_directory}\{(this_poke.lower())}-{(animations.lower())}_once({directions[idx]}).gif"
        canvas_frames[0].save(filename, format="GIF", append_images=canvas_frames[1:], save_all=True, loop=loop_value,
                              transparency=0, disposal=[2] * len(canvas_frames), duration=durations,
                              compress_level=0, save_local_palette=True, width=frame_width, height=frame_height)

我也会附上创建框架的方法:

def generate_gifs(anim_selected, animations, search_poke_number, this_poke):
    global photo_img, frames
    url = f'https://github.com/PMDCollab/SpriteCollab/blob/master/sprite/{int(search_poke_number[0]) + 1:04}/AnimData.xml?raw=true'
    response = requests.get(url)
    root = ET.fromstring(response.content)

    for anim in root.findall('./Anims/Anim'):
        if anim.find('Name').text == animations:
            frame_width = int(anim.find('FrameWidth').text)
            frame_height = int(anim.find('FrameHeight').text)
            frame_duration_values = [int(dur.text) * 20 for dur in anim.findall('./Durations/Duration')]

    shadow_size = root.find('ShadowSize').text

    anim_url = f'https://github.com/PMDCollab/SpriteCollab/blob/master/sprite/{int(search_poke_number[0]) + 1:04}/{animations}-Anim.png?raw=true'
    shadow_url = f'https://github.com/PMDCollab/SpriteCollab/blob/master/sprite/{int(search_poke_number[0]) + 1:04}/{animations}-Shadow.png?raw=true'
    response = requests.get(anim_url)
    anim_img = Image.open(io.BytesIO(response.content))
    response = requests.get(shadow_url)
    shadow_img = Image.open(io.BytesIO(response.content))

    shadow_arr = np.array(shadow_img)

    white = [255, 255, 255, 255]
    blue = [0, 0, 255, 255]
    green = [0, 255, 0, 255]
    red = [255, 0, 0, 255]
    black = [0, 0, 0, 255]
    transparent = [0, 0, 0, 0]

    colour_list = [white, green, red, blue]

    # Replace the colors with black or transparent based on shadow_size
    i = 0
    while i <= 3:
        if i <= int(shadow_size) + 1:
            shadow_arr[(shadow_arr == colour_list[i]).all(axis=2)] = black
        else:
            shadow_arr[(shadow_arr == colour_list[i]).all(axis=2)] = transparent
        i += 1

    shadow_img = Image.fromarray(shadow_arr)

    # Combine the images and merge them with the shadow image underneath
    merged_img = Image.alpha_composite(shadow_img, anim_img)
    photo_img = ImageTk.PhotoImage(merged_img)

    # Calculate the number of columns and rows in the sprite sheet
    num_cols = photo_img.width() // frame_width
    num_rows = photo_img.height() // frame_height

    # Create a list of PhotoImage objects for each frame in the GIF
    frames = [None] * (num_rows * num_cols)
    frame_count = 0
    for row in range(num_rows):
        for col in range(num_cols):
            x1 = col * frame_width
            y1 = row * frame_height

理论上,这都应该给我一个这样的GIF:

但是我得到了这样的 GIF:

编辑:所以在尝试了几天之后,它似乎与保存功能本身有关。即使我确保文件大小正确,当我尝试将它们一起保存为 gif 时,它们也会发生变化。即使将单个帧保存到文件夹并从中组装 gif 也会导致完全相同的问题。在这一点上,我只是在寻找替代方案/解决方法。

自上次编辑以来,我没有发现问题,也没有得到任何帮助。如果甚至有一个人对如何解决这个问题有一点点想法,那么我将不胜感激。

python python-imaging-library gif
© www.soinside.com 2019 - 2024. All rights reserved.