How to Convert WebP image to Gif with Python?
Asked Answered
T

2

6

I already tried this:

from PIL import Image
im = Image.open('this.webp')
im.save('that.gif', 'gif', save_all=True)

which is giving me this error

TypeError: unsupported operand type(s) for &: 'tuple' and 'int'

I have hundreds of webp images on my site and need to convert them to gif, because Firefox doesn't support it. Thank you.

Telangiectasis answered 25/8, 2018 at 10:33 Comment(4)
Which version of pillow are you using: I would suggest you to see this issue: github.com/python-pillow/Pillow/issues/2949Didache
I downgraded pillow from 5 to 4.3.0. It fixed the issue. Now the problem is the animations are gone.Telangiectasis
take a look at this @AzimjonPulatov https://mcmap.net/q/562049/-play-animations-in-gif-with-tkinter-duplicateCapybara
Please provide a WEP file that doesn't work for us to test with.Interknit
G
8

Set background to None before saving.

from PIL import Image
im = Image.open('this.webp')
im.info.pop('background', None)
im.save('that.gif', 'gif', save_all=True)

Thanks to: https://github.com/python-pillow/Pillow/issues/2949#issuecomment-419422861

Greeley answered 1/12, 2018 at 14:5 Comment(6)
is it possible to increase the quality of the resulted gif ?Potency
@FeraruSilviuMarian Yes probably. You should check the documentation of the pillow package.Greeley
Been doing it for hours to no availPotency
the saved file is using less colors it seemsPotency
@FeraruSilviuMarian i don't remember the process right now but it may be because of the default options.Greeley
@Greeley Thanks! Also take into account the possibility of a better transformation quality by setting these extra options: im.save(str(sys.argv[1]).replace('webp','gif'), 'gif', save_all=True, lossless=True, quality=100, method=6). Documentation hereSullyprudhomme
F
0

Here is a long but the additional muratgozel's answer considering the semi-transparent case.

def process_frame(frame):
    """
    Process GIF frame, repair edges, ensure no white or semi-transparent pixels, while keeping color information intact.
    """
    frame = frame.convert('RGBA')

    # Decompose Alpha channel
    alpha = frame.getchannel('A')

    # Process Alpha channel with threshold, remove semi-transparent pixels
    # Threshold can be adjusted as needed (0-255), 128 is the middle value
    threshold = 128
    alpha = alpha.point(lambda x: 255 if x >= threshold else 0)

    # Process Alpha channel with MinFilter, remove edge noise
    alpha = alpha.filter(ImageFilter.MinFilter(3))

    # Process Alpha channel with MaxFilter, repair edges
    alpha = alpha.filter(ImageFilter.MaxFilter(3))

    # Apply processed Alpha channel back to image
    frame.putalpha(alpha)

    return frame

def webp_to_gif(data: bytes) -> bytes:
    with tempfile.NamedTemporaryFile(suffix=".webp") as webp:
        webp.write(data)
        webp.flush()
        with tempfile.NamedTemporaryFile(suffix=".gif") as img:
            print(".", end="", flush=True)
            im = Image.open(webp.name)
            im.info.pop('background', None)
            frames = []
            duration = []

            for frame in ImageSequence.Iterator(im):
                frame = process_frame(frame)
                frames.append(frame)
                duration.append(frame.info.get('duration', 100))

            frames[0].save(img.name, save_all=True, lossless=True, quality=100, method=6,
                            append_images=frames[1:], loop=0, duration=duration, disposal=2)

            img.seek(0)
            return img.read()

Why is it so effective?

  1. Eliminate semi-transparent pixels:

    Threshold processing converts semi-transparent pixels into fully transparent or fully opaque pixels, respectively, thereby avoiding white or other noise at the edges.

  2. Smooth edges:

    The combined operation of erosion and dilation smoothes the edges of the image by shrinking and then expanding. Erosion can remove small noise points, and dilation can restore the main part – in this way, while eliminating small noise, large blocks of image information are retained as much as possible.

  3. Keep color information:

    Since only the Alpha channel is processed and the RGB color channels are not changed, the color information remains unchanged.

Due to space limitations, I documented the detailed reasoning steps and a complete conversion script in WebM/WebP to GIF with semi-transparency(xzos.net).

Facesaving answered 15/9 at 12:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.