Determining if a GIF is transparent in Python

2020-08-09 13:59发布

问题:

How would I go about checking if a GIF is transparent (even partially)?

I accomplished this with PNGs by opening the image up with PIL and checking the image's mode. But GIFs have the same mode regardless.

As for false positives I don't mind if a completely opaque GIF gets flagged as transparent (assuming this is a rare case), but I do mind if a transparent GIF gets flagged as being opaque.

As for libraries, I'd prefer a solution that uses PIL rather than something else, but whatever works.

回答1:

img = Image.open(filename)
if img.mode == "RGBA" or "transparency" in img.info:
    # image uses transparency

See here for how transparency works with GIF (and 8-bit, palettized, PNGs).

Note that your false positive case is possible: a GIF could define a color as transparent but not use it. I imagine this would be quite rare, though -- why throw a color away for transparency and not use it? (Your false negative is not possible.)

Still, if you need to know whether transparency is actually used, you can make two versions of the image in which the transparent color is mapped to different colors (say, black and white) and then compare them. If there are any differences, the image does use transparency. Like so:

def uses_transparency(filename):
    img = Image.open(filename)
    trans = img.info.get("transparency", None)
    if trans is not None:
        trans *= 3  # convert color number to palette table index
        palette = img.getpalette()
        imgs = []
        for bg in [0, 255]:   # map transparent color first to black, then white
            palette[trans:trans+3] = [bg] * 3
            img.putpalette(palette)
            imgs.append(img.convert("L"))
        return bool(ImageChops.difference(*imgs).getbbox())
    return False

You could use a similar approach to see whether a 24-bit PNG actually uses the alpha channel, by pasting it onto white and black backgrounds and comparing the results.