Marilyn
Marilyn

Reputation: 33

PIL , im.getdata() returning integers instead of tuples

I am writing a function that takes an image input, and returns a list of the RGB codes.

im = Image.open('picture.jpg')
pix = list(im.getdata())

pix should be a list of RGB tuples. In most cases it is, but I have found some cases like this:
[(244,255,255), (100,100,90), (23,0,80), ..., 220, (100,100,100)]

i.e. somehow im.getdata() is retreiving an integer from the pixel values??
Similarly, there are cases where one of the entires in pix is a 4-tuple: (1,0,0,255). Can someone explain why this is?
How can I change this so that I retrieve a list of only the RGB tuples of an image?
Any help or guidance would be appreciated!

Upvotes: 2

Views: 2401

Answers (1)

Mark Setchell
Mark Setchell

Reputation: 207758

Raster images can be stored in various ways - mainly in order to be efficient in terms of disk space and bandwidth required to transmit. Here are some of the options:

  • RGB triplets - this is the most common way for images to be stored and you get 3 values... 1 red, 1 green and 1 blue for each pixel,

  • RGBA quads - this means you have 4 values for each pixel... 1 red, 1 green, 1 blue and an alpha (A) value which specifies how opaque/transparent that pixel is,

  • greyscale - this means all pixels in the image are grey and you just get one value for each pixel specifying where it Sts on the scale between pure black (0) and pure white (255),

  • palettised - this means that there are fewer than 256 different colours in the image, and rather than store each one as 3 bytes of RGB, you just store the single byte for each pixel and use that to look up the corresponding value from the embedded table of 256 RGB values. This means you only 1 byte per pixel instead of 3.

    Notwithstanding all that, some images use 8 bits per sample. some use 16 bits, some use 32 bits and others use 64 bits. Also some use compression and some do not. But all this is independent and a separate issue from the list of points I made above.

If you want to be assured of always getting 3 values per pixel, just be sure to convert to RGB mode when you open:

im = Image.open('picture.jpg').convert('RGB')

Note that you may be needlessly increasing the memory you need to store the image (if greyscale or palettised) , or you may be discarding the alpha channel.

Another option is to get the type of the image and deal with the different cases:

# Open image 
im = Image.open('start.png')                                                                

# Check bands present - e.g. ('R', 'G', 'B')
bands = im.getbands() 
                                                                         

Upvotes: 2

Related Questions