Possible Duplicate:
What is the most “pythonic” way to iterate over a list in chunks?
I am reading in some PNG data, which has 4 channels per pixel. I would like to iterate over the data 1 pixel at a time (meaning every 4 elements = 1 pixel, rgba).
red_channel = 0
while red_channel < len(raw_png_data):
green_channel, blue_channel, alpha_channel = red_channel +1, red_channel +2, red_channel +3
# do something with my 4 channels of pixel data ... raw_png_data[red_channel] etc
red_channel += 4
This way doesnt really seem "right". Is there a more Pythonic way to iterate over a sequence, 4 items at a time, and have those 4 items unpacked?
(Python's itertools should really make all recipes as standard functions...)
You could use the grouper
function:
from itertools import zip_longest
def grouper(n, iterable, fillvalue=None):
"grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return izip_longest(fillvalue=fillvalue, *args)
Then you can iterate the pixels by
for r,g,b,a in grouper(4, raw_png_data):
....
Alternatively, you could use
irpd = iter(raw_png_data)
for r,g,b,a in zip(irpd, irpd, irpd, irpd): # use itertools.izip in Python 2.x
....
Note that this will chop the last few bytes if the iterable's length is not a multiple of 4. OTOH, the grouper
function uses izip_longest
, so the extra bytes will be padded with None for that.
vars = [1, 2, 3, 4, 5, 6, 7, 8]
for a, b, c, d in zip(*[iter(vars)]*4):
print a, b, c, d
from itertools import izip
for r,g,b,a in izip(*[iter(data)]*4):
...
for r, g, b, t in (data[i:i+4] for i in xrange(0, len(data)/4*4, 4)):
print r, g, b, t
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With