在 Python 中创建 PNG 文件

发布于 2024-12-22 07:31:34 字数 81 浏览 1 评论 0原文

我有一个应用程序,我希望能够从 Python 中的数据生成 PNG 图像。我做了一些搜索,发现“PIL”看起来相当过时。还有其他图书馆更适合这个吗?

I have an application where I would like to be able to generate PNG images from data in Python. I've done some searching and found "PIL" which looked pretty outdated. Is there some other library that would be better for this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

最美的太阳 2024-12-29 07:31:34

简单的 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]]))

Simple PNG files can be generated quite easily from pure Python code - all you need is the standard zlib module and some bytes-encoding to write the chunks. Here is a complete example that the casual reader may use as a starter for their own png generator:

#! /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]]))
野生奥特曼 2024-12-29 07:31:34

这是一个 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)

Here's a Python3 example:

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)
安静 2024-12-29 07:31:34

还有其他库更适合这个吗?

png 包将是一个合理的常见选择。

这是项目描述:

PyPNG 允许使用纯 Python 读取和写入 PNG 图像文件。

Is there some other library that would be better for this?

The png package would be a reasonable common choice.

Here's the project description:

PyPNG allows PNG image files to be read and written using pure Python.

﹏雨一样淡蓝的深情 2024-12-29 07:31:34

经过一番搜索后,我找到了这个网站: https://www.daniweb.com/programming/software-development/code/454765/save-a-pygame-drawing。它只是使用旧的 pygame。

第 37 行:(pg.image.save(win, fname)) 将 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

After doing some searching, I found this site: https://www.daniweb.com/programming/software-development/code/454765/save-a-pygame-drawing. It just uses good old pygame.

Line 37: (pg.image.save(win, fname)) saves whatever is drawn on the pygame surface as a file.

EDIT

Here is the actual code:

"""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
宫墨修音 2024-12-29 07:31:34

我知道这个问题是 9 年前提出的,但在 Python 3.8 时代,你可以以“写入二进制”模式打开文件:

f = open("filename.png", 'wb')
# data being whatever data you wanted to write
f.write(data)

I'm aware that this question was asked over 9 years ago, but in the age of Python 3.8, you can just open the file in "Writing Binary" mode:

f = open("filename.png", 'wb')
# data being whatever data you wanted to write
f.write(data)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文