Как создать изображение из строки в python

#python #python-imaging-library

#python #строка #изображение #сокеты

Вопрос:

В настоящее время у меня возникли проблемы с созданием изображения из двоичной строки данных в моей программе на Python. Я получаю двоичные данные через сокет, но когда я пробую методы, о которых я читал здесь, например:

 buff = StringIO.StringIO() #buffer where image is stored
#Then I concatenate data by doing a 
buff.write(data) #the data from the socket
im = Image.open(buff)
 

Я получаю исключение с эффектом «тип изображения не распознан». Я знаю, что получаю данные правильно, потому что, если я записываю изображение в файл, а затем открываю файл, он работает:

 buff = StringIO.StringIO() #buffer where image is stored
buff.write(data) #data is from the socket
output = open("tmp.jpg", 'wb')
output.write(buff)
output.close()
im = Image.open("tmp.jpg")
im.show()
 

Я полагаю, что, вероятно, я делаю что-то не так при использовании класса StringIO, но я не уверен

Комментарии:

1. В ответ на ваш комментарий о документировании StringIO: идея StringIO заключается в том, что это просто файл в памяти. Поведение было бы таким же для обычного файла на диске, если бы вы вызвали file . напишите(‘…’), затем file.read(), не возвращаясь к началу. Попробуй это 🙂

Ответ №1:

Я подозреваю, что вы не seek возвращаетесь к началу буфера, прежде чем передать объект StringIO в PIL. Вот некоторый код, демонстрирующий проблему и решение:

 >>> buff = StringIO.StringIO()
>>> buff.write(open('map.png', 'rb').read())
>>> 
>>> #seek back to the beginning so the whole thing will be read by PIL
>>> buff.seek(0)
>>>
>>> Image.open(buff)
<PngImagePlugin.PngImageFile instance at 0x00BD7DC8>
>>> 
>>> #that worked.. but if we try again:
>>> Image.open(buff)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "c:python25libsite-packagespil-1.1.6-py2.5-win32.eggImage.py", line 1916, in open
    raise IOError("cannot identify image file")
IOError: cannot identify image file
 

Убедитесь, что вы вызываете buff.seek(0) перед чтением любых объектов StringIO. В противном случае вы будете читать с конца буфера, который будет выглядеть как пустой файл и, вероятно, вызывает ошибку, которую вы видите.

Комментарии:

1. Я попробую это сделать завтра! Спасибо за идею

2. Спасибо за информацию. Модуль StringIO недостаточно хорошо документирован (по крайней мере, я смог найти)

3. Вы могли бы вместо этого сделать buff = StringIO.StringIO(open('map.png', 'rb').read()) . Больше не нужно seek() .

Ответ №2:

Вам нужно либо вызвать buff.seek(0) , либо, что еще лучше, инициализировать буфер памяти данными StringIO.StringIO(data) .