Байты Python PIL в изображение

import PIL
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
import urllib.request

with urllib.request.urlopen('http://pastebin.ca/raw/2311595') as in_file:
    hex_data = in_file.read()
print(hex_data)
img = Image.frombuffer('RGB', (320,240), hex_data) #i have tried fromstring
draw = ImageDraw.Draw(img)
font = ImageFont.truetype("arial.ttf",14)
draw.text((0, 220),"This is a test11",(255,255,0),font=font)
draw = ImageDraw.Draw(img)
img.save("a_test.jpg")

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

img = Image.frombuffer('RGB', (320,240), hex_data) 
raise ValueError("not enough image data")
ValueError: not enough image data

я загрузил строку байтов здесь http://pastebin.ca/raw/2311595
и размер изображения я уверен, что 320x240

ДОПОЛНИТЕЛЬНЫЙ

вот что я могу убедиться, что строка байтов изображения имеет размер 320x240, просто запустите код, который создаст изображение из строки байтов

import urllib.request
import binascii
import struct

# Download the data.
with urllib.request.urlopen('http://pastebin.ca/raw/2311595') as in_file:
     hex_data = in_file.read()
# Unhexlify the data.
bin_data = binascii.unhexlify(hex_data)
print(bin_data)
# Remove the embedded lengths.
jpeg_data = bin_data
# Write out the JPEG.
with open('out.jpg', 'wb') as out_file:
    out_file.write(jpeg_data)

РЕШЕНО, ЭТО КОД ОБНОВЛЕН

from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
import urllib.request
import io
import binascii

data = urllib.request.urlopen('http://pastebin.ca/raw/2311595').read()
r_data = binascii.unhexlify(data)
#r_data = "".unhexlify(chr(int(b_data[i:i+2],16)) for i in range(0, len(b_data),2))

stream = io.BytesIO(r_data)

img = Image.open(stream)
draw = ImageDraw.Draw(img)
font = ImageFont.truetype("arial.ttf",14)
draw.text((0, 220),"This is a test11",(255,255,0),font=font)
draw = ImageDraw.Draw(img)
img.save("a_test.png")

person Community    schedule 07.02.2013    source источник
comment
строка байтов имеет длину 118216 байт; как это может быть 320x240? RGB (3x8-битных пикселей, истинный цвет)   -  person Fredrik Pihl    schedule 08.02.2013
comment
вы можете попробовать bin_data = binascii.unhexlify(hex_data) байты, станет картинкой   -  person    schedule 08.02.2013
comment
@C.Y, когда я пытаюсь это сделать, я получаю только 9108 байт, этого недостаточно даже для 320x240 при 1 бите на пиксель.   -  person Mark Ransom    schedule 08.02.2013


Ответы (2)


Это изображение не состоит из необработанных байтов, а представляет собой закодированный файл JPEG. Более того, вы не разбираете ASCII HEX-представление потока на правильные байты: то есть последовательность «ff» в этом файле передается в PIL как две буквы c «f» вместо байта с номером 255.

Итак, во-первых, вы декодируете строку в правильную последовательность байтов - извините за свертку - вероятно, есть лучший способ сделать это, но у меня медленный день:

data = urllib.urlopen("http://pastebin.ca/raw/2311595").read()
r_data = "".join(chr(int(data[i:i+2],16)) for i in range(0, len(data),2)) 

А, С.Ю. размещенный в комментарии hte - таким образом:

>>> import binascii
>>> b_data = binascii.unhexlify(data)

И теперь вы импортируете его в PIL как изображение JPEG:

>>> from PIL import Image
>>> import cStringIO as StringIO
>>> stream = StringIO.StringIO(b_data)
>>> img = Image.open(stream)
>>> img.size
(320, 240)
person jsbueno    schedule 07.02.2013
comment
поднять IOError (не удается идентифицировать файл изображения) OSError: невозможно идентифицировать файл изображения # это ошибка, которую я получаю - person ; 08.02.2013
comment
К.Ю.: Вы выполнили правильное шестнадцатеричное декодирование (в двух предыдущих примерах) перед тем, как передать его в PIL? - person jsbueno; 08.02.2013
comment
@MarkRansom Я использую Python 3.3, и я обновил свой код, он не работает - person ; 08.02.2013
comment
@CY вернитесь к использованию unhexlify вместо join, поскольку Python 3 будет интерпретировать все эти байты как Unicode. - person Mark Ransom; 08.02.2013
comment
@CY Я не проверял ваш код или любой другой код в вопросе и ответе. Но уверены ли вы, что у вас действительно есть работающая сборка PIL? Релиза PIL для Python 3 не существует, используете ли вы какой-либо сторонний порт и гарантированно ли он будет работать точно так же, как официальный для Python 2 (обратите внимание, что PIL имеет очень ограниченный набор тестов, поэтому его прохождение гарантирует почти ничего)? - person mmgp; 08.02.2013
comment
@MarkRansom stream = io.StringIO(r_data) TypeError: initial_value должно быть str или None, а не байтами // после того, как я перейду на использование unhexlify, я получаю сообщение об ошибке - person ; 08.02.2013
comment
@C.Y использует BytesIO вместо StringIO. - person Mark Ransom; 08.02.2013
comment
@MarkRansom после того, как я нарисовал текст, я хочу преобразовать байты обратно и сохранить в Mysql Blob, как преобразовать обратно в строку байтов? - person ; 08.02.2013
comment
@C.Y Image.save должен сделать это обратно в другой объект BytesIO. - person Mark Ransom; 08.02.2013
comment
@MarkRansom, ты неправильно понял? я хочу преобразовать изображение в строку байтов и сохранить в базе данных Mysql. - person ; 08.02.2013

как говорят другие, Python 3 лучше использовать io.BytesIO

import io
from PIL import Image

imageFileObj = open(imageFilename, "rb")
imageBinaryBytes = imageFileObj.read()
imageStream = io.BytesIO(imageBinaryBytes)
imageFile = Image.open(imageStream)
print("imageFile.size=%s" % imageFile.size)
person crifan    schedule 23.12.2018