Кодування файлу зображення з base64


161

Я хочу кодувати зображення в рядок за допомогою модуля base64. Хоча я зіткнувся з проблемою. Як вказати зображення, яке я хочу кодувати? Я спробував використовувати каталог для зображення, але це просто призводить до того, що каталог кодується. Я хочу, щоб фактичний файл зображення був закодований.

EDIT

Я спробував цей фрагмент:

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))

але я отримую таку помилку:

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

Що я роблю неправильно?

Відповіді:


299

Я не впевнений, що розумію ваше запитання. Я припускаю, що ви щось робите:

import base64

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

Спершу потрібно відкрити файл і прочитати його вміст - ви не можете просто пройти шлях до функції кодування.

Редагувати: Гаразд, ось оновлення після редагування оригінального запитання.

Перш за все, не забудьте використовувати необроблені рядки (префікс рядка з 'r') при використанні роздільників шляху в Windows, щоб запобігти випадковому попаданню символу втечі. По-друге, PIL's Image.open або приймає ім'я файлу, або подібне до файлу (тобто об'єкт повинен забезпечувати методи читання, пошуку та підказки).

Зважаючи на це, ви можете використовувати cStringIO для створення такого об'єкта з буфера пам'яті:

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
Дякую, ще одна проблема, коли друкую розшифроване зображення, я отримую рядок "ÿØÿà". Однак, коли я запускаю це самостійно як заміну даних, я отримую помилку. Кодований рядок набагато довший для порівняння. Тому я думаю, що, ймовірно, зберігаються дані зображення. чи розшифровується рядок просто посилається на закодований рядок чи щось таке? Здається, це занадто мало для зберігання даних.
прямокутник прямокутник

Надрукований вихід не обов'язково дорівнює фактичному вмісту - це залежить від того, як і де ви його друкуєте.
Джим Бріссом

8
У моєму випадку мені потрібно розшифрувати: base64.b64encode(fh.read()).decode()щоб отримати рядок, який буде використаний у html-файлах.
qed

1
base64.b64encode (fh.read ()). decode () тонкий, але мені це було потрібно також @qed, дякую. Різниця - це один байт, який повертається, а інший рядок ... і мій сервер SOAP просто не проковтне його без розшифровки!
zzart

57

За допомогою python 2.x ви можете тривіально кодувати за допомогою .encode:

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

12

Перша відповідь надрукує рядок з префіксом b '. Це означає, що ваш рядок буде подібний до цього b'your_string 'Для вирішення цієї проблеми додайте наступний рядок коду.

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

2
Це виглядає як хороша відповідь, але, будь ласка, утримуйтесь від публікацій, якщо метою є просування вашого веб-сайту. Однак ви можете додати посилання у свій профіль.
півзахисник

1
(До речі, тут не можна покластися на порядок відповідей, тому варто уникати коментарів типу "перша відповідь". Перший, що з’явиться перший, може змінитися з часом. :-))
півзахисник

У початковій версії цієї відповіді виглядає так, що ви пов’язані зі своїм власним сайтом або сайтом, з яким ви пов’язані. Якщо ви робите посилання на такий сайт, ви повинні розкрити, що це ваш сайт . Якщо ви не розкриєте приналежність, це вважається спамом. Дивіться: Що означає "хороша" самореклама? та довідковий центр з питань самореклами . Розголошення має бути явним, але не повинно бути формальним. Коли це ваш власний особистий контент, він може просто бути на кшталт "на моєму сайті ...", "у моєму блозі ..." тощо.
Makyen

Дякую за пропозицію @Makyen, я хочу розкрити, що це мій сайт. Чи законно буде відредагувати відповідь зараз, щоб виявити, що це мій сайт? Або я не повинен це редагувати.
CodeSpeedy

9

Як я вже говорив у попередньому запитанні, немає необхідності базувати рядок base64, це лише зробить програму повільнішою. Просто використовуйте 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))
...

Тепер зображення зберігається у вигляді змінної, яка називається image_dataу файлі під назвою image.py Запустити новий інтерпретатор та імпортувати image_data

>>> from image import image_data
>>>

Я насправді не бачу, як репр () може бути тут корисним.
Іво ван дер Війк

6
@Ivo, Anteater хоче мати можливість зберігати зображення у файлах python. Я вказую, що використання base64 є контрпродуктивним, оскільки дані потрібно декодувати при кожному завантаженні модуля. Використання repr замість цього означає, що буквальна рядок зберігається готовим до негайного використання у файлі .pyc без подальшої обробки
John La Rooy

7

Запозичення з того, що ван - дер - Іво Вейк і gnibbler розробили раніше, це динамічне рішення

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')

Потім ви можете вирішити скласти файл вихідного зображення з Cython, щоб зробити його крутим. За допомогою цього методу ви можете поєднати всю вашу графіку в один модуль.


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
ця відповідь справді повинна бути вгорі ... найкраща - дякую!
Лютер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.