idiolect wrote: > On Jun 25, 7:26 pm, Terry Reedy <[EMAIL PROTECTED]> wrote: >> idiolect 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: >> >> Why are you trying to do this with a list comprehension? Learn the >> basics first. Perhaps you have read too many of the recent threads >> presenting diverting challenges for bored experienced programmers. Some >> of these were definitely not Pythonic code for real use. >> >> First question: do you really want to create a new 'very long list' or >> modify list 'data' in place. Let's assume the latter. >> >> for i,tup in enumerate(data): >> data[i] = replace(tup) >> >> where replace(tup) is an expression or function that produces a tuple >> meeting your criteria. Simplest is >> (max(tup[0],Rthresh), max(tup[1],Gthresh), max(tup[2],Bthresh)). >> >> If nearly all your pixels are ok, add the following before the >> assignment so you only make replacements when actually needed: >> if tup[0] < Rthresh or tup[1] < Gthresh or tup[2] < Bthresh: >> >> Terry Jan Reedy > > A giant thank-you to all who've posted in response to my query - these > are all much better approaches to my problem. I think I got hooked on > using a list comprehension as it seemed the most concise approach vs. > other techniques after a bunch of Google searches, but all of you have > pointed out more efficient methods. I appreciate your willingness to > indulge a n00b who hasn't thought his problem through, apparently. > I'll try all of these approaches out over the next day and see what > works best, although I suspect you've all posted sufficient solutions. > > Can't wait to try these suggestions out - cheers, idiolect
I'd like to emphasize Roger Miller's point with a small example script: #!/usr/bin/env python import sys import Image def transform_image_getdata(old, new): image = Image.open(old) image.putdata([(max(50, r), min(g*2, 255), 0) for r, g, b in image.getdata()]) image.save(new) def transform_image_point(old, new): image = Image.open(old) transform_red = [max(50, i) for i in range(256)] transform_green = [min(i*2, 255) for i in range(256)] transform_blue = [0 for i in range(256)] image.point(transform_red + transform_green + transform_blue).save(new) if __name__ == "__main__": import os, time def measure(f): def g(*args, **kw): start = time.time() try: return f(*args, **kw) finally: print f.__name__, time.time() - start return g for name in sys.argv[1:]: a, b = os.path.splitext(name) measure(transform_image_getdata)(name, a + ".getdata" + b) measure(transform_image_point)(name, a + ".point" + b) Run it: $ ./transform_image.py tmp.jpg transform_image_getdata 27.5557489395 transform_image_point 0.458500862122 For the example Image.point() is about 60 times faster than getdata(). It's the way to go if you can handle the color channels individually. Peter -- http://mail.python.org/mailman/listinfo/python-list