web-dev-qa-db-ja.com

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)

解決済み、これIS更新されたコード

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

その画像は生のバイトで構成されているのではなく、エンコードされたJPEGファイルです。さらに、ストリームのASCII HEX表現を適切なバイトに解析していません。つまり、そのファイル内の「ff」シーケンスは、255のバイトの代わりに2つのc文字「f」としてPILに渡されます。

そのため、最初に文字列を適切なバイトシーケンスにデコードします-たたみ込みでごめんなさい-それを行うより良い方法がある可能性がありますが、私は遅い日です:

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

ああ、C.Y。コメントに投稿-この方法:

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

そして今、あなたはそれをJPEG画像としてPILにインポートします:

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

他の言い方として、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)
4
crifan