I am using the following code coming (with very little modifications) from this post. This script simply takes an array of hex color and writes a PNG image out of it. I am trying to adapt it to Py3 but something is going wrong.
import zlib, struct
def png_pack(png_tag, data):
chunk_head = png_tag + data
return (struct.pack("!I", len(data)) +
struct.pack("!I", 0xFFFFFFFF & zlib.crc32(chunk_head)))
def write_png(buf, width, height):
# reverse the vertical line order and add null bytes at the start
width_byte_4 = width * 4
raw_data = b''.join(b'\x00' + buf[span:span + width_byte_4]
for span in range((height - 1) * width * 4, -1, - width_byte_4))
png_pack(b'IHDR', struct.pack("!2I5B", width, height, 8, 6, 0, 0, 0)),
png_pack(b'IDAT', zlib.compress(raw_data, 9)),
def saveAsPNG(array, filename):
if any([len(row) != len(array) for row in array]):
raise ValueError("Array should have elements of equal size")
#First row becomes top row of image.
flat = 
#Big-endian, unsigned 32-byte integer.
buf = b''.join([struct.pack('>I', ((0xffFFff & i32)<<8)|(i32>>24) )
for i32 in flat]) #Rotate from ARGB to RGBA.
data = write_png(buf, len(array), len(array))
f = open(filename, 'wb')
[0xff00aa77, 0xff333333]], 'test.png')
It works perfectly with Python 2.7 and run without raising any error on Python 3. However the resulting image is empty... I cannot figure out what's the problem. I tried to substitute
starmap but nothing changed. I have checked that
bytes instead of
string, and it is. I really don't know why it doesn't write the file correctly.
map returns a list. In Python3,
map returns a map object:
print(type(map(flat.extend, reversed(array)))) # <class 'map'>
The map object is an iterator. It does not call
flat.extend until it is iterated over. Since no variable is used to save the map object, it is discarded, and
flat remains an empty list.
So instead you need:
flat =  for item in reversed(array): flat.extend(item)
or a list comprehension:
flat = [item for arr in reversed(array) for item in arr]
import itertools as IT flat = IT.chain.from_iterable(reversed(array))
map should never be used for its side-effects. It should only be used for generating a list in Python2, or an iterator in Python3.
In Python2 using
map for its side-effects was a frowned-upon practice. In Python3, that policy is "enforced" to some degree by making
map an iterator.