32

How to detect if a PNG image has transparent alpha channel or not using PIL?

img = Image.open('example.png', 'r')
has_alpha = img.mode == 'RGBA'

With above code we know whether a PNG image has alpha channel not not but how to get the alpha value?

I didn't find a 'transparency' key in img.info dictionary as described at PIL's website

I'm using Ubuntu and zlib1g, zlibc packages are already installed.

jack
  • 17,261
  • 37
  • 100
  • 125

5 Answers5

62

To get the alpha layer of an RGBA image all you need to do is:

red, green, blue, alpha = img.split()

or

alpha = img.split()[-1]

And there is a method to set the alpha layer:

img.putalpha(alpha)

The transparency key is only used to define the transparency index in the palette mode (P). If you want to cover the palette mode transparency case as well and cover all cases you could do this

if img.mode in ('RGBA', 'LA') or (img.mode == 'P' and 'transparency' in img.info):
    alpha = img.convert('RGBA').split()[-1]

Note: The convert method is needed when the image.mode is LA, because of a bug in PIL.

Nadia Alramli
  • 111,714
  • 37
  • 173
  • 152
6

You can get the alpha data out of whole image in one go by converting image to string with 'A' mode e.g this example get alpha data out of image and saves it as grey scale image :)

from PIL import Image

imFile="white-arrow.png"
im = Image.open(imFile, 'r')
print im.mode == 'RGBA'

rgbData = im.tostring("raw", "RGB")
print len(rgbData)
alphaData = im.tostring("raw", "A")
print len(alphaData)

alphaImage = Image.fromstring("L", im.size, alphaData)
alphaImage.save(imFile+".alpha.png")
Anurag Uniyal
  • 85,954
  • 40
  • 175
  • 219
  • 2
    As of at least version 1.1.7 of PIL, this answer yields the error "NotImplementedError: tostring() has been removed. Please call tobytes() instead." – Simon Feb 19 '19 at 14:14
4

The img.info is about the image as a whole -- the alpha-value in an RGBA image is per-pixel, so of course it won't be in img.info. The getpixel method of the image object, given a coordinate as argument, returns a tuple with the values of the (four, in this case) bands for that pixel -- the tuple's last value will then be A, the alpha value.

Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
  • @Alex, thanks for your answer, is there a way to determine if a PNG image has a transparent background? – jack Dec 26 '09 at 07:50
  • 2
    Unless you are rarely doing this, `getpixel` will be really slow. You should use `getdata` or `load` for high performance access. – carl Dec 26 '09 at 09:45
4
# python 2.6+

import operator, itertools

def get_alpha_channel(image):
    "Return the alpha channel as a sequence of values"

    # first, which band is the alpha channel?
    try:
        alpha_index= image.getbands().index('A')
    except ValueError:
        return None # no alpha channel, presumably

    alpha_getter= operator.itemgetter(alpha_index)
    return itertools.imap(alpha_getter, image.getdata())
tzot
  • 92,761
  • 29
  • 141
  • 204
2

I tried this:

from PIL import Image
import operator, itertools

def get_alpha_channel(image): 
   try: 
      alpha_index = image.getbands().index('A')
   except ValueError:
      # no alpha channel, so convert to RGBA
      image = image.convert('RGBA')
      alpha_index = image.getbands().index('A')
   alpha_getter = operator.itemgetter(alpha_index)
   return itertools.imap(alpha_getter, image.getdata())

This returned the result that I was expecting. However, I did some calculation to determine the mean and standard deviation, and the results came out slightly different from imagemagick's fx:mean function.

Perhaps the conversion changed some of the values? I'm unsure, but it seems relatively trivial.

Zhia Chong
  • 346
  • 2
  • 12
  • You tried this so it answers the question or you have a similar problem but this code doesn't work as expected? In the latter case this should be a new question. In the former case it might need an edit to be less confusing? – rene Jan 12 '17 at 19:15
  • Oh thanks for the clarification. I tried this, and added something on to get what I needed. It was something of a similar case, and the latter was a new question, but I'm going with a different approach now because it seems like PIL has an issue with images that are in 'P' mode. – Zhia Chong Jan 12 '17 at 19:16