I am assisting in making a wiki for an old game, and we ripped the avatar GIFs from the games shop and want to have a catalog of them. What I need to do is to crop all the borders which are identical from 3,170 GIFs and maybe make background transparent.

I haven’t used python in years, but I managed to cobble up something that almost works as a single image test, only issue is that it crops and outputs only the first frame:

from PIL import Image

if __name__ == "__main__":
    input_loc = "AvatarShopImages/80001.gif"
    output_loc = "Output/80001.gif"
    im = Image.open(input_loc)
    im = im.crop((4, 4, 94, 94))
    im.save(output_loc)

If it looks weird, it is because I copy/pasted some code and edited a lot out of it.

  • UlrikHD@programming.dev
    link
    fedilink
    English
    arrow-up
    1
    ·
    1 year ago

    As others have suggested, ffmpeg is a great cli tool. If you aren’t comfortable with the terminal you can do it via python like this:

    import os
    import sys
    import subprocess
    
    
    def crop_media(file_name: str, w: int, h: int, x: int, y: int, new_dir: str) -> None:
        try:
            subprocess.run(f'ffmpeg -i "{file_name}" -vf "crop={w}:{h}:{x}:{y}" temp.gif -y',
                               shell=True, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
            os.rename('temp.gif', os.path.join(new_dir, file_name))
        # Print the error and continue with other gifs, remove try block if you want a complete stop
        except subprocess.CalledProcessError as e:
            print(e)
        except KeyboardInterrupt:
            print('KeyboardInterrupt, cleaning up files...')
            os.remove('temp.gif')
            sys.exit(0)
    
    
    def crop_directory(directory: str, w: int, h: int, x: int, y: int, new_dir: str) -> None:
        for root, _, files in directory:
            for file in files:
                if not file.endswith('.gif'):
                    continue
                if os.path.isfile(os.path.join(new_dir, file)):
                    print(f'{file} already exists in {new_dir}, skipping...')
                    continue
    
                file_path = os.path.normpath(os.path.join(root, file))
                crop_media(file_path, w, h, x, y, new_dir)
    
    
    if __name__ == '__main__':
        width = 0
        height = 0
        x_offset = 0
        y_offset = 0
        gif_directory = ''
        new_directory = ''
        crop_directory(gif_directory, width, height, x_offset, y_offset, new_directory)
    

    This should go through every file in the directory and subdirectories and call the ffmpeg command on each .gif. With new_directory you can set a directory to store every cropped .gif. The ffmpeg command is based on johnpiers suggestion.

    The script assumes unique filenames for each gif and should work with spaces in the filenames.