【发布时间】:2012-01-23 04:00:46
【问题描述】:
我有一个应用程序,我希望能够从 Python 中的数据生成 PNG 图像。我做了一些搜索,发现“PIL”看起来已经过时了。有没有其他图书馆可以更好地解决这个问题?
谢谢,
【问题讨论】:
-
您使用的是旧 PIL(如果您尚未开发 py3.2 之后的版本)
我有一个应用程序,我希望能够从 Python 中的数据生成 PNG 图像。我做了一些搜索,发现“PIL”看起来已经过时了。有没有其他图书馆可以更好地解决这个问题?
谢谢,
【问题讨论】:
【讨论】:
简单的PNG文件可以很容易地从纯Python代码生成——你只需要标准的zlib模块和一些字节编码来编写块。这是一个完整的示例,普通读者可以将其用作他们自己的 png 生成器的入门:
#! /usr/bin/python
""" Converts a list of list into gray-scale PNG image. """
__copyright__ = "Copyright (C) 2014 Guido Draheim"
__licence__ = "Public Domain"
import zlib
import struct
def makeGrayPNG(data, height = None, width = None):
def I1(value):
return struct.pack("!B", value & (2**8-1))
def I4(value):
return struct.pack("!I", value & (2**32-1))
# compute width&height from data if not explicit
if height is None:
height = len(data) # rows
if width is None:
width = 0
for row in data:
if width < len(row):
width = len(row)
# generate these chunks depending on image type
makeIHDR = True
makeIDAT = True
makeIEND = True
png = b"\x89" + "PNG\r\n\x1A\n".encode('ascii')
if makeIHDR:
colortype = 0 # true gray image (no palette)
bitdepth = 8 # with one byte per pixel (0..255)
compression = 0 # zlib (no choice here)
filtertype = 0 # adaptive (each scanline seperately)
interlaced = 0 # no
IHDR = I4(width) + I4(height) + I1(bitdepth)
IHDR += I1(colortype) + I1(compression)
IHDR += I1(filtertype) + I1(interlaced)
block = "IHDR".encode('ascii') + IHDR
png += I4(len(IHDR)) + block + I4(zlib.crc32(block))
if makeIDAT:
raw = b""
for y in xrange(height):
raw += b"\0" # no filter for this scanline
for x in xrange(width):
c = b"\0" # default black pixel
if y < len(data) and x < len(data[y]):
c = I1(data[y][x])
raw += c
compressor = zlib.compressobj()
compressed = compressor.compress(raw)
compressed += compressor.flush() #!!
block = "IDAT".encode('ascii') + compressed
png += I4(len(compressed)) + block + I4(zlib.crc32(block))
if makeIEND:
block = "IEND".encode('ascii')
png += I4(0) + block + I4(zlib.crc32(block))
return png
def _example():
with open("cross3x3.png","wb") as f:
f.write(makeGrayPNG([[0,255,0],[255,255,255],[0,255,0]]))
【讨论】:
这是一个 Python3 示例:
import png
width = 255
height = 255
img = []
for y in range(height):
row = ()
for x in range(width):
row = row + (x, max(0, 255 - x - y), y)
img.append(row)
with open('gradient.png', 'wb') as f:
w = png.Writer(width, height, greyscale=False)
w.write(f, img)
【讨论】:
经过一番搜索,我找到了这个网站:https://www.daniweb.com/programming/software-development/code/454765/save-a-pygame-drawing。它只是使用了旧的 pygame。
第 37 行将 pygame 表面上绘制的任何内容保存为文件。
编辑
下面是实际代码:
"""pg_draw_circle_save101.py
draw a blue solid circle on a white background
save the drawing to an image file
for result see http://prntscr.com/156wxi
tested with Python 2.7 and PyGame 1.9.2 by vegaseat 16may2013
"""
import pygame as pg
# pygame uses (r, g, b) color tuples
white = (255, 255, 255)
blue = (0, 0, 255)
width = 300
height = 300
# create the display window
win = pg.display.set_mode((width, height))
# optional title bar caption
pg.display.set_caption("Pygame draw circle and save")
# default background is black, so make it white
win.fill(white)
# draw a blue circle
# center coordinates (x, y)
center = (width//2, height//2)
radius = min(center)
# width of 0 (default) fills the circle
# otherwise it is thickness of outline
width = 0
# draw.circle(Surface, color, pos, radius, width)
pg.draw.circle(win, blue, center, radius, width)
# now save the drawing
# can save as .bmp .tga .png or .jpg
fname = "circle_blue.png"
pg.image.save(win, fname)
print("file {} has been saved".format(fname))
# update the display window to show the drawing
pg.display.flip()
# (press escape key or click window title bar x to exit)
while True:
for event in pg.event.get():
if event.type == pg.QUIT:
# most reliable exit on x click
pg.quit()
raise SystemExit
elif event.type == pg.KEYDOWN:
# optional exit with escape key
if event.key == pg.K_ESCAPE:
pg.quit()
raise SystemExit
【讨论】:
我知道这个问题是在 9 年前提出的,但在 Python 3.8 时代,您可以在“Writing Binary”模式下打开文件:
f = open("filename.png", 'wb')
# data being whatever data you wanted to write
f.write(data)
【讨论】: