PIL не может идентифицировать файл изображения для объекта io.BytesIO

Я использую вилку Pillow PIL и продолжаю получать ошибку

OSError: невозможно идентифицировать файл образа < _io.BytesIO объект в 0x103a47468 >

при попытке открыть изображение. Я использую virtualenv с python 3.4 и не устанавливаю PIL.

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

from PIL import Image
import io

# This portion is part of my test code
byteImg = Image.open("some/location/to/a/file/in/my/directories.png").tobytes()

# Non test code
dataBytesIO = io.BytesIO(byteImg)
Image.open(dataBytesIO) # <- Error here

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

EDIT:

dataBytesIO.seek(0)

не работает как решение (попробовал), так как я не сохраняю изображение через поток, я просто создаю BytesIO с данными, поэтому (если я думаю об этом правильно), поиск уже должен быть при 0.

Ответ 1

(Это решение принадлежит самому автору. Я только что перевел его сюда.)

РЕШЕНИЕ:

# This portion is part of my test code
byteImgIO = io.BytesIO()
byteImg = Image.open("some/location/to/a/file/in/my/directories.png")
byteImg.save(byteImgIO, "PNG")
byteImgIO.seek(0)
byteImg = byteImgIO.read()


# Non test code
dataBytesIO = io.BytesIO(byteImg)
Image.open(dataBytesIO)

Проблема заключалась в том, что Image.tobytes() возвращал объект байта. Он оказался недействительным, а "кодирование" не могло быть чем-то иным, чем необработанным, которое по-прежнему выдавало неверные данные, поскольку почти каждый байт появился в формате \xff\. Тем не менее, сохранение байтов через BytesIO и использование функции .read() для чтения всего изображения дало правильные байты, которые в случае необходимости позже могли быть действительно использованы.

Ответ 2

При чтении файлов Dicom проблема может быть вызвана сжатием Dicom. Убедитесь, что и gdcm, и pydicom установлены.

GDCM обычно более сложен в установке. Последний способ легко установить это

conda install -U conda-forge gdcm

Ответ 3

В некоторых случаях такая же ошибка возникает, когда вы имеете дело с файлом Raw Image, таким как CR2. Пример: http://www.rawsamples.ch/raws/canon/g10/RAW_CANON_G10.CR2

когда вы пытаетесь запустить:

byteImg = Image.open("RAW_CANON_G10.CR2")

Вы получите эту ошибку:

OSError: cannot identify image file 'RAW_CANON_G10.CR2'

Поэтому вам нужно сначала конвертировать изображение с помощью rawkit, вот пример того, как это сделать:

from io import BytesIO
from PIL import Image, ImageFile
import numpy
from rawkit import raw
def convert_cr2_to_jpg(raw_image):
    raw_image_process = raw.Raw(raw_image)
    buffered_image = numpy.array(raw_image_process.to_buffer())
    if raw_image_process.metadata.orientation == 0:
        jpg_image_height = raw_image_process.metadata.height
        jpg_image_width = raw_image_process.metadata.width
    else:
        jpg_image_height = raw_image_process.metadata.width
        jpg_image_width = raw_image_process.metadata.height
    jpg_image = Image.frombytes('RGB', (jpg_image_width, jpg_image_height), buffered_image)
    return jpg_image

byteImg = convert_cr2_to_jpg("RAW_CANON_G10.CR2")

Код кредита, если для mateusz-michalik на GitHub (https://github.com/mateusz-michalik/cr2-to-jpg/blob/master/cr2-to-jpg.py)

Ответ 4

Это случилось со мной при случайной загрузке PDF вместо PNG.