调整 Python 3 的工作代码会生成一个空白的 PNG
Adapting working code for Python 3 produces a blank PNG
我正在使用来自 this post 的以下代码(几乎没有修改)。该脚本简单地获取一个十六进制颜色数组并从中写入一个 PNG 图像。我正在尝试使其适应 Py3,但出了点问题。
import zlib, struct
def png_pack(png_tag, data):
chunk_head = png_tag + data
return (struct.pack("!I", len(data)) +
chunk_head +
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))
return b''.join([
b'\x89PNG\r\n\x1a\n',
png_pack(b'IHDR', struct.pack("!2I5B", width, height, 8, 6, 0, 0, 0)),
png_pack(b'IDAT', zlib.compress(raw_data, 9)),
png_pack(b'IEND', b'')])
def saveAsPNG(array, filename):
import struct
if any([len(row) != len(array[0]) for row in array]):
raise ValueError("Array should have elements of equal size")
#First row becomes top row of image.
flat = []
map(flat.extend, reversed(array))
#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.
#print(type(buf))
data = write_png(buf, len(array[0]), len(array))
f = open(filename, 'wb')
f.write(data)
f.close()
saveAsPNG([[0xffFF0000, 0xffFFFF00],
[0xff00aa77, 0xff333333]], 'test.png')
它与 Python 2.7 和 运行 完美配合,不会在 Python 3 上引发任何错误。但是生成的图像是空的...我无法弄清楚问题出在哪里。我尝试用 starmap
替换 map
但没有任何改变。我检查过 buf
是 bytes
而不是 string
,确实如此。我真的不知道为什么它没有正确写入文件。
有什么线索吗?
在Python2、map
、returns列表中。在 Python3、map
returns a map object:
print(type(map(flat.extend, reversed(array))))
# <class 'map'>
地图对象是一个迭代器。在迭代之前它不会调用 flat.extend
。由于没有使用变量来保存地图对象,它被丢弃,flat
仍然是一个空列表。
所以你需要:
flat = []
for item in reversed(array):
flat.extend(item)
flat = [item for arr in reversed(array) for item in arr]
或itertools.chain.from_iterable:
import itertools as IT
flat = IT.chain.from_iterable(reversed(array))
map
永远不应该使用它的副作用。它应该只用于生成 Python2 中的列表或 Python3 中的迭代器。
在 Python2 中使用 map
作为其副作用是一种不受欢迎的做法。在 Python3 中,通过使 map
成为迭代器,该策略在某种程度上是 "enforced"。
我正在使用来自 this post 的以下代码(几乎没有修改)。该脚本简单地获取一个十六进制颜色数组并从中写入一个 PNG 图像。我正在尝试使其适应 Py3,但出了点问题。
import zlib, struct
def png_pack(png_tag, data):
chunk_head = png_tag + data
return (struct.pack("!I", len(data)) +
chunk_head +
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))
return b''.join([
b'\x89PNG\r\n\x1a\n',
png_pack(b'IHDR', struct.pack("!2I5B", width, height, 8, 6, 0, 0, 0)),
png_pack(b'IDAT', zlib.compress(raw_data, 9)),
png_pack(b'IEND', b'')])
def saveAsPNG(array, filename):
import struct
if any([len(row) != len(array[0]) for row in array]):
raise ValueError("Array should have elements of equal size")
#First row becomes top row of image.
flat = []
map(flat.extend, reversed(array))
#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.
#print(type(buf))
data = write_png(buf, len(array[0]), len(array))
f = open(filename, 'wb')
f.write(data)
f.close()
saveAsPNG([[0xffFF0000, 0xffFFFF00],
[0xff00aa77, 0xff333333]], 'test.png')
它与 Python 2.7 和 运行 完美配合,不会在 Python 3 上引发任何错误。但是生成的图像是空的...我无法弄清楚问题出在哪里。我尝试用 starmap
替换 map
但没有任何改变。我检查过 buf
是 bytes
而不是 string
,确实如此。我真的不知道为什么它没有正确写入文件。
有什么线索吗?
在Python2、map
、returns列表中。在 Python3、map
returns a map object:
print(type(map(flat.extend, reversed(array))))
# <class 'map'>
地图对象是一个迭代器。在迭代之前它不会调用 flat.extend
。由于没有使用变量来保存地图对象,它被丢弃,flat
仍然是一个空列表。
所以你需要:
flat = []
for item in reversed(array):
flat.extend(item)
flat = [item for arr in reversed(array) for item in arr]
或itertools.chain.from_iterable:
import itertools as IT
flat = IT.chain.from_iterable(reversed(array))
map
永远不应该使用它的副作用。它应该只用于生成 Python2 中的列表或 Python3 中的迭代器。
在 Python2 中使用 map
作为其副作用是一种不受欢迎的做法。在 Python3 中,通过使 map
成为迭代器,该策略在某种程度上是 "enforced"。