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

161

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

РЕДАКТИРОВАТЬ

Я попробовал этот фрагмент:

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

Что я делаю не так?

rectangletangle
источник

Ответы:

299

Я не уверен, что понимаю ваш вопрос. Я предполагаю, что вы делаете что-то вроде:

import base64

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

Конечно, сначала нужно открыть файл и прочитать его содержимое - вы не можете просто передать путь к функции кодирования.

Изменить: Хорошо, вот обновление после того, как вы отредактировали свой первоначальный вопрос.

Прежде всего, не забывайте использовать необработанные строки (с префиксом «r») при использовании разделителей пути в Windows, чтобы предотвратить случайное попадание escape-символа. Во-вторых, PIL 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'))
CodeSpeedy
источник
2
Это выглядит как хороший ответ, но, пожалуйста, воздержитесь от публикации, если целью является продвижение вашего сайта. Вы можете добавить ссылки в свой профиль, однако.
Halfer
1
(Между прочим, здесь нельзя полагаться на порядок ответов, поэтому стоит избегать комментариев, таких как «первый ответ». Тот, который появляется первым, может со временем меняться. :-))
Полуостров
В исходной версии этого ответа вы видите, что вы ссылаетесь на свой собственный сайт или сайт, с которым вы связаны. Если вы делаете ссылку на такой сайт, вы должны сообщить, что это ваш сайт . Если вы не раскрываете принадлежность, это считается спамом. Видите: Что означает "Хорошая" самореклама? и справочный центр по саморекламе . Раскрытие должно быть явным, но не должно быть формальным. Когда это ваш личный контент, это может быть что-то вроде «на моем сайте…», «в моем блоге…» и т. Д.
Makyen
Спасибо за предложение @Makyen Я собираюсь раскрыть, что это мой сайт. Будет ли законным редактировать ответ сейчас, чтобы раскрыть, что это мой сайт? Или я не должен редактировать это.
CodeSpeedy
9

Как я уже говорил в вашем предыдущем вопросе, нет необходимости кодировать строку в base64, это только замедлит работу программы. Просто используйте репр

>>> 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
>>>
Джон Ла Рой
источник
Я действительно не понимаю, как repr () может быть здесь полезным.
Иво ван дер Вейк
6
@ Ivo, Anteater хочет иметь возможность хранить изображения в файлах Python. Я отмечаю, что использование base64 контрпродуктивно, потому что данные необходимо декодировать каждый раз при загрузке модуля. Использование repr вместо этого означает, что буквенная строка сохраняется готовой к немедленному использованию в файле .pyc без дальнейшей обработки
John La Rooy
7

Заимствование из того, что Ivo van der Wijk и 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, чтобы он был классным. С помощью этого метода вы можете объединить всю графику в один модуль.

iChux
источник
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')

Программные решения DooDle
источник
1
этот ответ действительно должен быть наверху ... лучший - спасибо!
Лютер