Newbie question about tuples and list comprehensions

Matimus mccredie at gmail.com
Wed Jun 25 17:58:54 EDT 2008


On Jun 25, 2:37 pm, idiolect <boingy.boi... at gmail.com> wrote:
> Hi all - Sorry to plague you with another newbie question from a
> lurker.  Hopefully, this will be simple.
>
> I have a list full of RGB pixel values read from an image.  I want to
> test each RGB band value per pixel, and set it to something else if it
> meets or falls below a certain threshold - i.e., a Red value of 0
> would be changed to 50.
>
> I've built my list by using a Python Image Library statement akin to
> the following:
>
> data = list(image.getdata())
>
> Which produces a very long list that looks like [(0,150,175),
> (50,175,225),...].  I'm trying to figure out a fast and pythonic way
> to perform my operation.  The closest I've come so far to a succinct
> statement is a list comprehension along the syntax of:
>
> source = [((x,y,z),(x+50,y+50,z+50))[bool(x or y or z < 50)] for
> (x,y,z) in source]
>
> ...which kind of approaches the effect I'm looking for, but it doesn't
> really test and change each value in the tuple individually.  My
> understanding of the things you can do with lists and python in
> general is rather naive, so I would appreciate any insight anyone can
> offer since I am not sure if I'm even headed down the correct path
> with list comprehensions.
>
> Much obliged!

List comprehension is just a tool. If it looks more complicated than
it would if you used a regular for loop, then use a regular for loop.

It seems like you are evaluating a lot of data, so I would take
advantage of pythons (lazy) generators to save a lot of memory:

def brighten(seq, threshold=50): # I don't know what the generic name
for this operation is
    for pixel in seq:
       if any(channel < threshold for channel in pixel):
           r, g, b = pixel
           yield r + threshold, g + threshold, b + threshold

then...

source = brighten(image.getdata())

Source is going to be a lazy generator, so you can cast it to list, or
just pass it to something else that takes a sequence. The latter is
preferred.

Matt



More information about the Python-list mailing list