Python PIL bytes to Image

72,775

Solution 1

That image is not formed of raw bytes - rather it is an encoded JPEG file. Moreover, you are not parsing the ascii HEX representation of the stream into proper bytes: that is, an "ff" sequence in that file is being passed to PIL as two c letters "f" instead of a byte with the number 255.

So, first, you decode the string to a proper byte sequence - sorry for the convolution - it is likely there is a better way to do that, but I am on a slow day:

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. posted on hte comment - this way:

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

And now, you import it to PIL as a JPEG image:

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

Solution 2

as other say, Python 3 better use 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)
Share:
72,775
evandrix
Author by

evandrix

nondescript

Updated on August 04, 2022

Comments

  • evandrix
    evandrix almost 2 years
    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")
    

    i m trying to convert binary to image,and then draw the text.but i get the error with:

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

    i have uploaded the bytes string at here http://pastebin.ca/raw/2311595
    and the picture size i can sure that is 320x240

    ADDITIONAL

    here is what i can sure the picture bytes string are from 320x240,just run the code will create a image from the bytes string

    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)
    

    SOLVED, THIS IS THE CODE UPDATED

    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")
    
    • Fredrik Pihl
      Fredrik Pihl about 11 years
      the bytestring is 118216 bytes long; how can that be 320x240? RGB (3x8-bit pixels, true colour)
    • Admin
      Admin about 11 years
      you can try bin_data = binascii.unhexlify(hex_data) the bytes,will become a picture
    • Mark Ransom
      Mark Ransom about 11 years
      @C.Y when I try that I only get 9108 bytes, that's not even enough for 320x240 at 1 bit per pixel.
  • Admin
    Admin about 11 years
    raise IOError("cannot identify image file") OSError: cannot identify image file #this is the error i get
  • jsbueno
    jsbueno about 11 years
    C.Y.: did youdo the proper hex-decoding (in the 2 previous examples) before passing it to PIL?
  • Admin
    Admin about 11 years
    @MarkRansom i m using python 3.3, and i have updated my code,it doesn't work
  • Mark Ransom
    Mark Ransom about 11 years
    @C.Y go back to using unhexlify instead of join since Python 3 will interpret all those bytes as Unicode.
  • mmgp
    mmgp about 11 years
    @C.Y I didn't check your code or any other code in the question and answer. But, are you sure you actually have a working PIL build ? There is no PIL release for Python 3, are you using some third-party port and is it guaranteed to work in exactly the same way of the official one for Python 2 (note that PIL has a very limited test suite, so passing it guarantees nearly nothing) ?
  • Admin
    Admin about 11 years
    @MarkRansom stream = io.StringIO(r_data) TypeError: initial_value must be str or None, not bytes //after i change to use unhexlify i get the error
  • Mark Ransom
    Mark Ransom about 11 years
    @C.Y use BytesIO instead of StringIO.
  • Admin
    Admin about 11 years
    @MarkRansom after i draw the text,i want to convert back bytes and store in Mysql Blob,how to convert back to bytes string?
  • Mark Ransom
    Mark Ransom about 11 years
    @C.Y Image.save back into another BytesIO object should do it.
  • Admin
    Admin about 11 years
    @MarkRansom are you missunderstanding? i want to convert img to bytes string.and store in Mysql database.
  • Pedro P. Camellon
    Pedro P. Camellon over 2 years
    I'm reading a png file from within a zip and this worked for me. Thanks!