Làm thế nào để viết hình ảnh PNG thành chuỗi với PIL?


99

Tôi đã tạo một hình ảnh bằng PIL . Làm cách nào để lưu nó vào một chuỗi trong bộ nhớ? Các Image.save()phương pháp đòi hỏi một tập tin.

Tôi muốn có một số hình ảnh như vậy được lưu trữ trong từ điển.

Câu trả lời:


194

Bạn có thể sử dụng BytesIOlớp để lấy một trình bao bọc xung quanh các chuỗi hoạt động giống như một tệp. Đối BytesIOtượng cung cấp giao diện giống như một tệp, nhưng chỉ lưu nội dung trong bộ nhớ:

import io

with io.BytesIO() as output:
    image.save(output, format="GIF")
    contents = output.getvalue()

Bạn phải chỉ định rõ ràng định dạng đầu ra với formattham số, nếu không PIL sẽ phát sinh lỗi khi cố gắng tự động phát hiện nó.

Nếu bạn tải hình ảnh từ một tệp, nó có một formattham số chứa định dạng tệp gốc, vì vậy trong trường hợp này bạn có thể sử dụng format=image.format.

Trong các phiên bản Python 2 cũ trước khi giới thiệu iomô-đun, bạn sẽ sử dụng StringIOmô-đun đó thay thế.


1
Đúng! Điều này thật đúng với gì mà tôi đã tìm kiếm. Tôi truy cập vào mọi tổ hợp của python, string, reader, writer, buffer và không tìm ra bất cứ thứ gì. Cảm ơn!
rik.the.vik

2
Không làm việc cho tôi :( Tôi đã KeyError này trong Imaging / PIL / Image.pyc dòng 1423 -> tăng KeyError (ext) # chưa biết mở rộng
Radian

6
@Radian, Tài liệu PIL về phương thức save () cho biết: You can use a file object instead of a filename. In this case, you must always specify the format.Vì vậy, nếu đối số đầu tiên là một đối tượng tệp, bạn phải chuyển đối số thứ hai, đó là định dạng (ví dụ 'PNG').
Su Zhang

1
Trong phiên bản Python hiện tại, StringIO nằm trong gói io, bạn phải viết:from io import StringIO
Spoutnik.

4
bạn có thể sử dụng tốt hơnimage.save(output, format=image.format)
reetesh11


24

giải pháp của sth không hiệu quả với tôi
vì trong ...

Imaging / PIL / Image.pyc dòng 1423 -> nâng KeyError (ext) # phần mở rộng không xác định

Nó đang cố gắng phát hiện định dạng từ phần mở rộng trong tên tệp, không tồn tại trong trường hợp StringIO

Bạn có thể bỏ qua việc phát hiện định dạng bằng cách tự đặt định dạng trong một tham số

import StringIO
output = StringIO.StringIO()
format = 'PNG' # or 'JPEG' or whatever you want
image.save(output, format)
contents = output.getvalue()
output.close()

14

save()có thể lấy một đối tượng giống tệp cũng như một đường dẫn, vì vậy bạn có thể sử dụng bộ đệm trong bộ nhớ như StringIO:

buf = StringIO.StringIO()
im.save(buf, format='JPEG')
jpeg = buf.getvalue()

Cảm ơn bạn. StringIO - đó là những gì tôi cần.
maxp

Giao diện save () gọn gàng hơn nhiều so với giao diện tostring () khi nói đến định dạng tệp PNG, JPEG hoặc thực tế.
Kekoa

13

Với hiện đại (kể từ giữa năm 2017 Python 3.5 và Pillow 4.0):

StringIO dường như không còn hoạt động như trước đây nữa. Lớp BytesIO là cách thích hợp để xử lý điều này. Hàm lưu của Pillow mong đợi một chuỗi là đối số đầu tiên và đáng ngạc nhiên là không thấy StringIO như vậy. Phần sau tương tự với các giải pháp StringIO cũ hơn, nhưng với BytesIO ở vị trí của nó.

from io import BytesIO
from PIL import Image

image = Image.open("a_file.png")
faux_file = BytesIO()
image.save(faux_file, 'png')

2
mục đích của, image_data = faux_file.getvalue () là gì?
Ryan

@Ryan Bắt tốt, không có mục đích gì cả. Nó còn sót lại sau quá trình thử nghiệm và cuối cùng đã bị loại bỏ.
powerspile

9

Khi bạn nói "Tôi muốn có số lượng hình ảnh như vậy được lưu trữ trong từ điển", không rõ đây có phải là cấu trúc trong bộ nhớ hay không.

Bạn không cần phải làm bất kỳ điều gì trong số này để ghi nhớ một hình ảnh trong bộ nhớ. Chỉ cần giữ imageđối tượng trong từ điển của bạn.

Nếu bạn định ghi từ điển của mình vào một tệp, bạn có thể muốn xem xét im.tostring()phương thức và Image.fromstring()hàm

http://effbot.org/imagingbook/image.htm

im.tostring () => chuỗi

Trả về một chuỗi chứa dữ liệu pixel, sử dụng bộ mã hóa "thô" tiêu chuẩn.

Image.fromstring (mode, size, data) => image

Tạo bộ nhớ hình ảnh từ dữ liệu pixel trong một chuỗi, sử dụng bộ giải mã "thô" tiêu chuẩn.

"Định dạng" (.jpeg, .png, v.v.) chỉ quan trọng trên đĩa khi bạn đang trao đổi tệp. Nếu bạn không trao đổi tệp, định dạng không quan trọng.


2
Có vẻ như anh ấy muốn giữ lại định dạng PNG, không giảm nó thành dữ liệu pixel thô.
Ben Blank
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.