Tôi có một ứng dụng mà tôi muốn có thể tạo ra hình ảnh PNG từ dữ liệu bằng Python. Tôi đã thực hiện một số tìm kiếm và tìm thấy "PIL" trông khá lỗi thời. Có thư viện nào khác tốt hơn cho điều này không?Tạo tệp PNG bằng Python
Cảm ơn,
Tôi có một ứng dụng mà tôi muốn có thể tạo ra hình ảnh PNG từ dữ liệu bằng Python. Tôi đã thực hiện một số tìm kiếm và tìm thấy "PIL" trông khá lỗi thời. Có thư viện nào khác tốt hơn cho điều này không?Tạo tệp PNG bằng Python
Cảm ơn,
Các tệp PNG đơn giản có thể được tạo dễ dàng từ mã Python thuần túy - tất cả những gì bạn cần là mô-đun zlib chuẩn và một số byte mã hóa để ghi các khối. Dưới đây là một ví dụ hoàn chỉnh mà người đọc thông thường có thể sử dụng làm khởi động cho máy phát điện png riêng của mình:
#! /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]]))
Sâu hơn một chút so với hầu hết chúng ta, có thể bao gồm OP, đang tìm kiếm, nhưng +1 để chia sẻ rất nhiều thông tin. Đây là tài liệu tham khảo tuyệt vời nếu tôi muốn đi sâu hơn với png. – mightypile
Ví dụ này thật tuyệt vời. Bất kỳ thay đổi nào bạn có thể thay đổi để hiển thị cách thêm bảng màu (đối với một số màu đỏ/xanh lục/vv cơ bản và có kênh alpha)? – 576i
Tôi muốn cung cấp một câu trả lời rất ngắn. Rõ ràng có khá nhiều tùy chọn để xây dựng và mã hóa hình ảnh. May mắn là tiêu chuẩn PNG khá rõ ràng về những gì để đưa vào mỗi đoạn (https://www.w3.org/TR/PNG). Để tránh bit nhồi một trong những chỉ đơn giản là sẽ tìm các tùy chọn để luôn luôn mã hóa một giá trị vào chính xác một byte. ///// Đối với một RGBA có thể rất đơn giản: một đoạn PLTE không có tùy chọn mã hóa => nó luôn luôn chính xác 8 bit cho mỗi kênh màu, không nhiều hơn và không ít hơn. Vì vậy, mỗi mục nhập là 4 byte (R, G, B, A). Các bit IepDR đề cập đến IDAT - với 8 bit một có thể viết chỉ số byte một lần nữa. –
PIL đã lỗi thời như thế nào? –
bạn sử dụng PIL cũ tốt (nếu bạn chưa phát triển vượt quá py3.2) – joaquin