web-dev-qa-db-fra.com

Python octets PIL à l'image

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")

j'essaye de convertir le binaire en image, puis dessine le texte, mais j'obtiens l'erreur avec:

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

j'ai téléchargé la chaîne d'octets ici http://Pastebin.ca/raw/2311595
et la taille de l'image je peux être sûr que c'est 320x240

ADDITIONNEL

voici ce que je peux vous assurer que la chaîne d'octets d'image est de 320x240, il suffit d'exécuter le code créera une image à partir de la chaîne d'octets

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)

RÉSOLU, CECI IS LE CODE MIS À JOUR

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")
19
user2040602

Cette image n'est pas formée d'octets bruts - c'est plutôt un fichier JPEG encodé. De plus, vous n'analysez pas la représentation ascii HEX du flux en octets appropriés: c'est-à-dire qu'une séquence "ff" dans ce fichier est passée à PIL en deux lettres c "f" au lieu d'un octet avec le nombre 255.

Donc, d'abord, vous décodez la chaîne dans une séquence d'octets appropriée - désolé pour la convolution - il est probable qu'il existe une meilleure façon de le faire, mais je suis un jour lent:

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)) 

Ah, C.Y. posté sur le commentaire hte - de cette façon:

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

Et maintenant, vous l'importez dans PIL en tant qu'image JPEG:

>>> from PIL import Image
>>> import cStringIO as StringIO
>>> stream = StringIO.StringIO(b_data)
>>> img = Image.open(stream)
>>> img.size
(320, 240)
16
jsbueno

comme d'autres disent, Python 3 mieux utiliser 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)
4
crifan