Mã hóa một tập tin hình ảnh với base64


161

Tôi muốn mã hóa một hình ảnh thành một chuỗi bằng mô-đun base64. Tôi đã gặp phải một vấn đề mặc dù. Làm cách nào để chỉ định hình ảnh tôi muốn được mã hóa? Tôi đã thử sử dụng thư mục cho hình ảnh, nhưng điều đó chỉ đơn giản dẫn đến thư mục được mã hóa. Tôi muốn tập tin hình ảnh thực tế được mã hóa.

BIÊN TẬP

Tôi đã thử đoạn trích này:

with open("C:\Python26\seriph1.BMP", "rb") as f:
    data12 = f.read()
    UU = data12.encode("base64")
    UUU = base64.b64decode(UU)

    print UUU

    self.image = ImageTk.PhotoImage(Image.open(UUU))

nhưng tôi nhận được lỗi sau:

Traceback (most recent call last):
  File "<string>", line 245, in run_nodebug
  File "C:\Python26\GUI1.2.9.py", line 473, in <module>
    app = simpleapp_tk(None)
  File "C:\Python26\GUI1.2.9.py", line 14, in __init__
    self.initialize()
  File "C:\Python26\GUI1.2.9.py", line 431, in initialize
    self.image = ImageTk.PhotoImage(Image.open(UUU))
  File "C:\Python26\lib\site-packages\PIL\Image.py", line 1952, in open
    fp = __builtin__.open(fp, "rb")
TypeError: file() argument 1 must be encoded string without NULL bytes, not str

Tôi đang làm gì sai?

Câu trả lời:


299

Tôi không chắc là tôi hiểu câu hỏi của bạn. Tôi giả sử bạn đang làm một cái gì đó dọc theo dòng:

import base64

with open("yourfile.ext", "rb") as image_file:
    encoded_string = base64.b64encode(image_file.read())

Bạn phải mở tệp trước tiên và đọc nội dung của nó - bạn không thể đơn giản chuyển đường dẫn đến hàm mã hóa.

Chỉnh sửa: Ok, đây là một bản cập nhật sau khi bạn đã chỉnh sửa câu hỏi ban đầu của mình.

Trước hết, hãy nhớ sử dụng các chuỗi thô (tiền tố của chuỗi có 'r') khi sử dụng các dấu phân cách đường dẫn trên Windows, để tránh việc vô tình nhấn một ký tự thoát. Thứ hai, Image.open của PIL chấp nhận tên tệp hoặc giống như tệp (nghĩa là, đối tượng phải cung cấp các phương thức đọc, tìm và nói).

Điều đó đang được nói, bạn có thể sử dụng cStringIO để tạo một đối tượng như vậy từ bộ nhớ đệm:

import cStringIO
import PIL.Image

# assume data contains your decoded image
file_like = cStringIO.StringIO(data)

img = PIL.Image.open(file_like)
img.show()

1
Cảm ơn, một vấn đề nữa khi tôi in hình ảnh được giải mã tôi nhận được chuỗi '' Øÿà '. Tuy nhiên, khi tôi chạy cái này một mình để thay thế cho dữ liệu, tôi gặp lỗi. Chuỗi được mã hóa dài hơn nhiều để so sánh. Vì vậy, tôi nghĩ rằng có khả năng lưu trữ dữ liệu hình ảnh. chuỗi giải mã chỉ đơn giản là tham chiếu chuỗi được mã hóa hay cái gì đó? Có vẻ như quá ngắn để lưu trữ dữ liệu.
hình chữ nhật

Đầu ra được in không nhất thiết phải bằng với nội dung thực tế - nó phụ thuộc vào cách thức và nơi bạn in nó.
Jim Brissom

8
Trong trường hợp của tôi, tôi cần giải mã: base64.b64encode(fh.read()).decode()để có được một chuỗi được sử dụng trong các tệp html.
qed

1
base64.b64encode (fh.read ()). decode () là tinh tế nhưng tôi cũng cần điều này @qed, cảm ơn. Sự khác biệt là một trả về byte và chuỗi khác ... và máy chủ SOAP của tôi sẽ không nuốt nó mà không giải mã!
zzart

57

Với python 2.x, bạn có thể mã hóa tầm thường bằng cách sử dụng .encode:

with open("path/to/file.png", "rb") as f:
    data = f.read()
    print data.encode("base64")

12

Câu trả lời đầu tiên sẽ in một chuỗi có tiền tố b '. Điều đó có nghĩa là chuỗi của bạn sẽ giống như b'your_opes 'này để giải quyết vấn đề này, vui lòng thêm dòng mã sau đây.

encoded_string= base64.b64encode(img_file.read())
print(encoded_string.decode('utf-8'))

2
Đây có vẻ là một câu trả lời tốt, nhưng xin vui lòng không đăng nếu mục đích là để quảng bá trang web của bạn. Bạn được chào đón để thêm liên kết vào hồ sơ của bạn, tuy nhiên.
halfer

1
(Ngẫu nhiên, thứ tự câu trả lời không thể được dựa vào đây, vì vậy, đáng để tránh các bình luận như "câu trả lời đầu tiên". Câu trả lời xuất hiện đầu tiên có thể thay đổi theo thời gian. :-))
halfer

Trong phiên bản gốc của câu trả lời này, có vẻ như bạn đã liên kết với trang web của riêng bạn hoặc một trang web mà bạn liên kết. Nếu bạn liên kết đến một trang web như vậy, bạn phải tiết lộ rằng đó là trang web của bạn . Nếu bạn không tiết lộ liên kết, nó được coi là thư rác. Xem: Điều gì biểu thị sự tự quảng cáo "Tốt"? trung tâm trợ giúp về tự quảng cáo . Tiết lộ phải rõ ràng, nhưng không cần phải chính thức. Khi đó là nội dung cá nhân của riêng bạn , nó có thể giống như "trên trang web của tôi", "trên blog của tôi", v.v.
Makyen

Cảm ơn lời đề nghị @Makyen Tôi sẽ tiết lộ rằng đó là trang web của tôi. Sẽ là hợp pháp để chỉnh sửa câu trả lời ngay bây giờ để tiết lộ rằng đó là trang web của tôi? Hoặc tôi không nên chỉnh sửa nó.
CodeSpeedy

9

Như tôi đã nói trong câu hỏi trước của bạn, không cần mã hóa base64 chuỗi, nó sẽ chỉ làm cho chương trình chậm hơn. Chỉ cần sử dụng repr

>>> with open("images/image.gif", "rb") as fin:
...  image_data=fin.read()
...
>>> with open("image.py","wb") as fout:
...  fout.write("image_data="+repr(image_data))
...

Bây giờ hình ảnh được lưu trữ dưới dạng một biến được gọi image_datatrong một tệp có tên image.py Bắt đầu một trình thông dịch mới và nhập image_data

>>> from image import image_data
>>>

Tôi thực sự không thấy làm thế nào repr () có thể được sử dụng ở đây.
Ivo van der Wijk

6
@Ivo, Anteater muốn có thể lưu trữ hình ảnh trong các tệp python. Tôi chỉ ra rằng việc sử dụng base64 là phản tác dụng vì dữ liệu cần được giải mã mỗi khi mô-đun được tải. Thay vào đó, sử dụng repr có nghĩa là chuỗi ký tự được lưu trữ sẵn sàng để sử dụng ngay lập tức trong tệp .pyc mà không cần xử lý furthur
John La Rooy

7

Mượn từ những gì Ivo van der Wijkgnibbler đã phát triển trước đó, đây là một giải pháp năng động

import cStringIO
import PIL.Image

image_data = None

def imagetopy(image, output_file):
    with open(image, 'rb') as fin:
        image_data = fin.read()

    with open(output_file, 'w') as fout:
        fout.write('image_data = '+ repr(image_data))

def pytoimage(pyfile):
    pymodule = __import__(pyfile)
    img = PIL.Image.open(cStringIO.StringIO(pymodule.image_data))
    img.show()

if __name__ == '__main__':
    imagetopy('spot.png', 'wishes.py')
    pytoimage('wishes')

Sau đó, bạn có thể quyết định biên dịch tệp hình ảnh đầu ra với Cython để làm cho nó mát mẻ. Với phương pháp này, bạn có thể bó tất cả đồ họa của mình vào một mô-đun.


7
import base64
from PIL import Image
from io import BytesIO

with open("image.jpg", "rb") as image_file:
    data = base64.b64encode(image_file.read())

im = Image.open(BytesIO(base64.b64decode(data)))
im.save('image1.png', 'PNG')

1
câu trả lời này thực sự nên ở đầu ... tốt nhất - cảm ơn!
Luther
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.