How to create an image from a string in python - python

I'm currently having trouble creating an image from a binary string of data in my Python program. I receive the binary data via a socket but when I try the methods I read about on here like this:
buff = StringIO.StringIO() #buffer where image is stored
#Then I concatenate data by doing a
buff.write(data) #the data from the socket
im = Image.open(buff)
I get an exception to the effect of "image type not recognized". I know that I am receiving the data correctly because if I write the image to a file and then open a file it works:
buff = StringIO.StringIO() #buffer where image is stored
buff.write(data) #data is from the socket
output = open("tmp.jpg", 'wb')
output.write(buff)
output.close()
im = Image.open("tmp.jpg")
im.show()
I figure I am probably doing something wrong in using the StringIO class but I'm not sure

I suspect that you're not seek-ing back to the beginning of the buffer before you pass the StringIO object to PIL. Here's some code the demonstrates the problem and solution:
>>> buff = StringIO.StringIO()
>>> buff.write(open('map.png', 'rb').read())
>>>
>>> #seek back to the beginning so the whole thing will be read by PIL
>>> buff.seek(0)
>>>
>>> Image.open(buff)
<PngImagePlugin.PngImageFile instance at 0x00BD7DC8>
>>>
>>> #that worked.. but if we try again:
>>> Image.open(buff)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "c:\python25\lib\site-packages\pil-1.1.6-py2.5-win32.egg\Image.py", line 1916, in open
raise IOError("cannot identify image file")
IOError: cannot identify image file
Make sure you call buff.seek(0) before reading any StringIO objects. Otherwise you'll be reading from the end of the buffer, which will look like an empty file and is likely causing the error you're seeing.

You have either call buff.seek(0) or, better, initialize memory buffer with data StringIO.StringIO(data).

Related

How to serialize a image into str and deserialize it as image?

I need to send an jpg image over network via json. I tried to convert the data into str via base64, as below:
from PIL import Image
from tinydb import TinyDB, Query
import base64
import io
from pdb import set_trace as bp
# note: with 'encoding' in name, it is always a bytes obj
in_jpg_encoding = None
# open some randome image
with open('rkt2.jpg', 'rb') as f:
# The file content is a jpeg encoded bytes object
in_jpg_encoding = f.read()
# output is a bytes object
in_b64_encoding = base64.b64encode(in_jpg_encoding)
# interpret above bytes as str, because json value need to be string
in_str = in_b64_encoding.decode(encoding='utf-8')
# in_str = str(in_b64_encoding) # alternative way of above statement
# simulates a transmission, e.g. sending the image data over internet using json
out_str = in_str
# strip-off the utf-8 interpretation to restore it as a base64 encoding
out_utf8_encoding = out_str.encode(encoding='utf-8')
# out_utf8_encoding = out_str.encode() # same way of writing above statement
# strip off the base64 encoding to restore it as its original jpeg encoded conent
# note: output is still a bytes obj due to b64 decoding
out_b64_decoding = base64.b64decode(out_utf8_encoding)
out_jpg_encoding = out_b64_decoding
# ---- verification stage
out_jpg_file = io.BytesIO(out_jpg_encoding)
out_jpg_image = Image.open(out_jpg_file)
out_jpg_image.show()
But I got error at the deserialization stage, saying the cannot identify the image as file:
Traceback (most recent call last):
File "3_test_img.py", line 38, in <module>
out_jpg_image = Image.open(out_jpg_file)
File "/home/gaopeng/Envs/venv_celeb_parser/lib/python3.6/site-packages/PIL/Image.py", line 2687, in open
% (filename if filename else fp))
OSError: cannot identify image file <_io.BytesIO object at 0x7f6f823c6b48>
Did I missed something?

Python PyMuPDF Fitz insertImage

Have been trying to put an image into a PDF file using PyMuPDF / Fitz and everywhere I look on the internet I get the same syntax, but when I use it I'm getting a runtime error.
>>> doc = fitz.open("NewPDF.pdf")
>>> page = doc[1]
>>> rect = fitz.Rect(0,0,880,1080)
>>> page.insertImage(rect, filename = "Image01.jpg")
error: object is not a stream
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python27\lib\site-packages\fitz\fitz.py", line 1225, in insertImage
return _fitz.Page_insertImage(self, rect, filename, pixmap, overlay)
RuntimeError: object is not a stream
>>> page
page 1 of NewPDF.pdf
I've tried a few different variations on this, with pixmap and without, with overlay value set, and without. The PDF file exists and can be opened with Adobe Acrobat Reader, and the image file exists - I have tried PNG and JPG.
Thank you in advanced for any help.
just some hints to attempt:
Ensure that your "Image01.jpg" file is open and use the full path.
image_path = "/full/path/to/Image01.jpg"
image_file = Image.open(
open(image_path, 'rb'))
# side-note: generally it is better to use the open with syntax, see link below
# https://stackoverflow.com/questions/9282967/how-to-open-a-file-using-the-open-with-statement
To ensure that you are actually on the pdf page that you expect to be, try this. This code will insert the image only on the first page
for page in doc:
page.InsertImage(rect, filename=image_path)
break # Without this, the image will appear on each page of your pdf

save base64 image python

I am trying to save an image with python that is Base64 encoded. Here the string is to large to post but here is the image
And when received by python the last 2 characters are == although the string is not formatted so I do this
import base64
data = "data:image/png;base64," + photo_base64.replace(" ", "+")
And then I do this
imgdata = base64.b64decode(data)
filename = 'some_image.jpg' # I assume you have a way of picking unique filenames
with open(filename, 'wb') as f:
f.write(imgdata)
But this causes this error
Traceback (most recent call last):
File "/var/www/cgi-bin/save_info.py", line 83, in <module>
imgdata = base64.b64decode(data)
File "/usr/lib64/python2.7/base64.py", line 76, in b64decode
raise TypeError(msg)
TypeError: Incorrect padding
I also printed out the length of the string once the data:image/png;base64, has been added and the spaces replace with + and it has a length of 34354, I have tried a bunch of different images but all of them when I try to open the saved file say that the file is damaged.
What is happening and why is the file corrupt?
Thanks
EDIT
Here is some base64 that also failed
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADBQTFRFA6b1q Ci5/f2lt/9yu3 Y8v2cMpb1/DSJbz5i9R2NLwfLrWbw m T8I8////////SvMAbAAAABB0Uk5T////////////////////AOAjXRkAAACYSURBVHjaLI8JDgMgCAQ5BVG3//9t0XYTE2Y5BPq0IGpwtxtTP4G5IFNMnmEKuCopPKUN8VTNpEylNgmCxjZa2c1kafpHSvMkX6sWe7PTkwRX1dY7gdyMRHZdZ98CF6NZT2ecMVaL9tmzTtMYcwbP y3XeTgZkF5s1OSHwRzo1fkILgWC5R0X4BHYu7t/136wO71DbvwVYADUkQegpokSjwAAAABJRU5ErkJggg==
This is what I receive in my python script from the POST Request
Note I have not replace the spaces with +'s
There is no need to add data:image/png;base64, before, I tried using the code below, it works fine.
import base64
data = 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADBQTFRFA6b1q Ci5/f2lt/9yu3 Y8v2cMpb1/DSJbz5i9R2NLwfLrWbw m T8I8////////SvMAbAAAABB0Uk5T////////////////////AOAjXRkAAACYSURBVHjaLI8JDgMgCAQ5BVG3//9t0XYTE2Y5BPq0IGpwtxtTP4G5IFNMnmEKuCopPKUN8VTNpEylNgmCxjZa2c1kafpHSvMkX6sWe7PTkwRX1dY7gdyMRHZdZ98CF6NZT2ecMVaL9tmzTtMYcwbP y3XeTgZkF5s1OSHwRzo1fkILgWC5R0X4BHYu7t/136wO71DbvwVYADUkQegpokSjwAAAABJRU5ErkJggg=='.replace(' ', '+')
imgdata = base64.b64decode(data)
filename = 'some_image.jpg' # I assume you have a way of picking unique filenames
with open(filename, 'wb') as f:
f.write(imgdata)
If you append data:image/png;base64, to data, then you get error. If You have this, you must replace it.
new_data = initial_data.replace('data:image/png;base64,', '')

How to open a simple image using streams in Pillow-Python

from PIL import Image
image = Image.open("image.jpg")
file_path = io.BytesIO();
image.save(file_path,'JPEG');
image2 = Image.open(file_path.getvalue());
I get this error TypeError: embedded NUL character on the last statement Image.open on running the program
What is the correct way to open a file from streams?
http://effbot.org/imagingbook/introduction.htm#more-on-reading-images
from PIL import Image
import StringIO
buffer = StringIO.StringIO()
buffer.write(open('image.jpeg', 'rb').read())
buffer.seek(0)
image = Image.open(buffer)
print image
# <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=800x600 at 0x7FE2EEE2B098>
# if we try open again
image = Image.open(buffer)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/dist-packages/PIL/Image.py", line 2028, in open
raise IOError("cannot identify image file")
IOError: cannot identify image file
Make sure you call buff.seek(0) before reading any StringIO objects. Otherwise you'll be reading from the end of the buffer, which will look like an empty file and is likely causing the error you're seeing.
Using BytesIO is much more simple, it took me a while to figure out. This allows you to read and write to zip files for example.
from PIL import Image
from io import BytesIO
# bytes of a simple 2x2 gif file
gif_bytes = b'\x47\x49\x46\x38\x39\x61\x02\x00\x02\x00\x80\x00\x00\x00\xFF\xFF\xFF\x21\xF9\x04\x00\x00\x00\x00\x00\x2C\x00\x00\x00\x00\x02\x00\x02\x00\x00\x02\x03\x44\x02\x05\x00\x3B'
gif_bytes_io = BytesIO() # or io.BytesIO()
# store the gif bytes to the IO and open as image
gif_bytes_io.write(gif_bytes)
image = Image.open(gif_bytes_io)
# optional proof of concept:
# image.show()
# save as png through a stream
png_bytes_io = BytesIO() # or io.BytesIO()
image.save(png_bytes_io, format='PNG')
print(png_bytes_io.getvalue()) # outputs the byte stream of the png

Encoding an image file with base64

I want to encode an image into a string using the base64 module. I've ran into a problem though. How do I specify the image I want to be encoded? I tried using the directory to the image, but that simply leads to the directory being encoded. I want the actual image file to be encoded.
EDIT
I tried this snippet:
with open("C:\Python26\seriph1.BMP", "rb") as f:
data12 = f.read()
UU = data12.encode("base64")
UUU = base64.b64decode(UU)
print UUU
self.image = ImageTk.PhotoImage(Image.open(UUU))
but I get the following error:
Traceback (most recent call last):
File "<string>", line 245, in run_nodebug
File "C:\Python26\GUI1.2.9.py", line 473, in <module>
app = simpleapp_tk(None)
File "C:\Python26\GUI1.2.9.py", line 14, in __init__
self.initialize()
File "C:\Python26\GUI1.2.9.py", line 431, in initialize
self.image = ImageTk.PhotoImage(Image.open(UUU))
File "C:\Python26\lib\site-packages\PIL\Image.py", line 1952, in open
fp = __builtin__.open(fp, "rb")
TypeError: file() argument 1 must be encoded string without NULL bytes, not str
What am I doing wrong?
I'm not sure I understand your question. I assume you are doing something along the lines of:
import base64
with open("yourfile.ext", "rb") as image_file:
encoded_string = base64.b64encode(image_file.read())
You have to open the file first of course, and read its contents - you cannot simply pass the path to the encode function.
Edit:
Ok, here is an update after you have edited your original question.
First of all, remember to use raw strings (prefix the string with 'r') when using path delimiters on Windows, to prevent accidentally hitting an escape character. Second, PIL's Image.open either accepts a filename, or a file-like (that is, the object has to provide read, seek and tell methods).
That being said, you can use cStringIO to create such an object from a memory buffer:
import cStringIO
import PIL.Image
# assume data contains your decoded image
file_like = cStringIO.StringIO(data)
img = PIL.Image.open(file_like)
img.show()
The first answer will print a string with prefix b'.
That means your string will be like this b'your_string' To solve this issue please add the following line of code.
encoded_string= base64.b64encode(img_file.read())
print(encoded_string.decode('utf-8'))
I have experienced this while converting Image to Base64 string. You can take a look at how I removed that from there also. Link is here Image to base64 string and fix 'b from prefix
import base64
from PIL import Image
from io import BytesIO
with open("image.jpg", "rb") as image_file:
data = base64.b64encode(image_file.read())
im = Image.open(BytesIO(base64.b64decode(data)))
im.save('image1.png', 'PNG')
Borrowing from what Ivo van der Wijk and gnibbler have developed earlier, this is a dynamic solution
import cStringIO
import PIL.Image
image_data = None
def imagetopy(image, output_file):
with open(image, 'rb') as fin:
image_data = fin.read()
with open(output_file, 'w') as fout:
fout.write('image_data = '+ repr(image_data))
def pytoimage(pyfile):
pymodule = __import__(pyfile)
img = PIL.Image.open(cStringIO.StringIO(pymodule.image_data))
img.show()
if __name__ == '__main__':
imagetopy('spot.png', 'wishes.py')
pytoimage('wishes')
You can then decide to compile the output image file with Cython to make it cool. With this method, you can bundle all your graphics into one module.
As I said in your previous question, there is no need to base64 encode the string, it will only make the program slower. Just use the repr
>>> with open("images/image.gif", "rb") as fin:
... image_data=fin.read()
...
>>> with open("image.py","wb") as fout:
... fout.write("image_data="+repr(image_data))
...
Now the image is stored as a variable called image_data in a file called image.py
Start a fresh interpreter and import the image_data
>>> from image import image_data
>>>
Its work for me
import base64
import requests
# Getting image in bytes
response = requests.get("image_url")
# image encoding
encoded_image = base64.b64encode(response.content)
# image decoding and without it's won't work due to some '\xff' error
decoded_image= base64.b64decode(encoded_image)

Categories

Resources