Кодування файлу зображення з 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.