Search code examples
pythonanimated-gifpython-imageio

set imageio compression level in python


I'm using imageio in Python to read in jpg images and write them as a gif, using something resembling the code below.

import imageio

with imageio.get_writer('mygif.gif', mode='I') as writer:
    for filename in framefiles:    # iterate over names of jpg files I want to turn into gif frames
    frame = imageio.imread(filename)
    writer.append_data(frame)

I'm noticing that the image quality in the gifs I produce is quite poor; I suspect this is due to some form of compression. Is there a way to tell imageio not to use any compression? Or maybe a way to do this with opencv instead?


Solution

  • Real problem is that GIF can display only 256 colors (8-bits color) so it has to reduce 24-bits colors (RGB) to 256 colors or it has emulate more colors using dots with different colors - ditherring.


    As for options:

    Digging in source code I found that it can get two parameters quantizer, palettesize which can control image/animation quality. (There is also subrectangles to reduce file size)

    But there are two plugins for GIF which use different modules Pillow or FreeImage and they need different value for quantizer

    PIL needs integer 0, 1 or 2.

    FI needs string 'wu' or 'nq' (but later it converts it to integer 0 or 1)

    They also keep these values in different way so if you want get current value or change it after get_writer() then you also need different code.

    You can select module with format='GIF-PIL' or format='GIF-FI'

    with imageio.get_writer('mygif.gif', format='GIF-PIL', mode='I', 
                            quantizer=2, palettesize=32) as writer:
        print(writer)
        #print(dir(writer))
        #print(writer._writer)
        #print(dir(writer._writer))
    
        print('quantizer:', writer._writer.opt_quantizer)
        print('palette_size:', writer._writer.opt_palette_size)
    
        #writer._writer.opt_quantizer = 1
        #writer._writer.opt_palette_size = 256
        #print('quantizer:', writer._writer.opt_quantizer)
        #print('palette_size:', writer._writer.opt_palette_size)
    
    
    with imageio.get_writer('mygif.gif', format='GIF-FI', mode='I', 
                            quantizer='nq', palettesize=32) as writer:
        print(writer)
        #print(dir(writer))
    
        print('quantizer:', writer._quantizer)
        print('palette_size:', writer._palettesize)
    
        #writer._quantizer = 1
        #writer._palettesize = 256
        #print('quantizer:', writer._quantizer)
        #print('palette_size:', writer._palettesize)
    

    I tried to create animations with different settings but they don't look much better.

    I get better result using external program ImageMagick in console/terminal

    convert image*.jpg mygif.gif
    

    but still it wasn't as good as video or static images.

    You can run it in Python

    os.system("convert image*.jpg mygif.gif")
    
    subprocess.run("convert image*.jpg mygif.gif", shell=True)
    

    Or you can try to do it with module Wand which is a wrapper on ImageMagick


    Source code: GifWriter in pillowmulti.py and in freeimagemulti.py

    * wu - Wu, Xiaolin, Efficient Statistical Computations for Optimal Color Quantization
    * nq (neuqant) - Dekker A. H., Kohonen neural networks for optimal color quantization
    

    Doc: GIF-PIL Static and animated gif (Pillow), GIF-FI Static and animated gif (FreeImage)