Store base64 string image to MongoDB using Gridfs - python

I am currently trying to store an image in the form of base64 string to the MongoDB using GridFS, here is my working solution so far:
def upload(image_string):
image_data = base64.b64decode(image_string)
image = Image.open(io.BytesIO(image_data))
image.save("foo.jpeg")
with open("foo.jpeg", "rb") as img:
storage = GridFS(mongo.mydb, "fs")
storage.put(img, content_type='image/jpeg')
I was wondering if there is a way to directly upload the image instead of saving the image as a file and read it again for the Gridfs to upload? (Google App Engine doesn't allow file storage)
I looked at the documentation of the put function of Gridfs, but it is quite unclear on the exact type of data type it is taking.
"data can be either an instance of str (bytes in python 3) or a file-like object providing a read() method."
How do I convert the base64 string to bytes that gridfs supports?

Gridfs put method accepts binaries.
# encode your image to binary text
with open("unnamed.jpg", "rb") as image:
# read the image as text and convert it to binary
image_string = base64.b64encode(image.read())
# create Gridfs instance
fs = gridfs.GridFS(db)
# add the image to your database
put_image = fs.put(image_string)

Related

Store a base64 image in python memory, then retrieve for use in wxpython/PIL

1) I have an image that I converted to a string. It looks like this:
bytesimage = b'iVBORw0KGgoAAAANSUhEUgA.... etc etc
2) I can convert it to an 'bytesimage.png' using:
def StringToImage(self, stringname, imageoutput):
imgdata = base64.b64decode(stringname)
imagename = imageoutput
with open(imagename, 'wb') as f:
f.write(imgdata)
3) But then I want to save that image or string to memory to use in wxpython interface without needing to save the file. I have seen several related questions where the solution is using io.BytesIO, but I just cant connect the steps and both wxpython or PIL don't seem to read the bytes properly.
So to clarify:
I have a image stored in a string DONE
I can convert that to an image (if needed) but dont want to save it DONE
I need that string OR image (whichever is best) saved to memory NEEDS SOLVING
Then I want to be able to use that image in wxpython (I can open in PIL first if required)
Any help would be fantastic!
StringIO seems to be the way to go. It allows you to pass the decoded string directly to PIL.
import base64
from PIL import Image
import StringIO
# Banana emoji (JPG) as a b64 string.
b64_img_str = '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'
# Decode back to the original bytes
new_img_str = base64.b64decode(b64_img_str)
# Use StringIO to provide an in-memory buffer that we can use
# to pass the image string to PIL.
sio = StringIO.StringIO(new_img_str)
img = Image.open(sio)
# Display the image
img.show()

How to convert image data type from windows sql server to image using python?

I need to convert compressed image column data from windows sql server to image file and save it to file system.
data is in github gist
I am using Python 2.7.2, Pillow on mac.
Thank you !
What I did was opening your gist in my browser, then save as... to a file named 'chenchi.txt'.
I then used this program to convert the hex-encoded string to raw bytes and load them into Pillow to make an image out of it:
from PIL import Image
import StringIO
import binascii
# In your case, 's' will be the string from the field
# in the database.
s = open("chenchi.txt").read()
# chop off the '0x' at the front.
s = s[2:]
# Decode it to binary.
binary = binascii.unhexlify(s)
# Wrap the bytes in a memory stream that can be read like a file.
bytes = StringIO.StringIO(binary)
# Use pillow to read the memory stream into an image (it autodetects the format).
im = Image.open(bytes)
# And show it. Or you could .save() it.
im.show()
Worked to me using b16decode.
My exported image from sql is something like that: 'FFD8FFE000104A46494600010101004800480000FFE13...'
So I had to convert the content and saved into a file.
source = 'data.dat'
destination = 'data.jpg'
with open(source, 'r') as f:
content = f.read()
content = base64.b16decode(content)
with open(destination, 'wb') as g:
g.write(content)

How can a Pygame surface be converted to an image file say a jpeg or a png WITHOUT writing the file to disk? Say after a screen grab? [duplicate]

I have generated an image using PIL. How can I save it to a string in memory?
The Image.save() method requires a file.
I'd like to have several such images stored in dictionary.
You can use the BytesIO class to get a wrapper around strings that behaves like a file. The BytesIO object provides the same interface as a file, but saves the contents just in memory:
import io
with io.BytesIO() as output:
image.save(output, format="GIF")
contents = output.getvalue()
You have to explicitly specify the output format with the format parameter, otherwise PIL will raise an error when trying to automatically detect it.
If you loaded the image from a file it has a format property that contains the original file format, so in this case you can use format=image.format.
In old Python 2 versions before introduction of the io module you would have used the StringIO module instead.
For Python3 it is required to use BytesIO:
from io import BytesIO
from PIL import Image, ImageDraw
image = Image.new("RGB", (300, 50))
draw = ImageDraw.Draw(image)
draw.text((0, 0), "This text is drawn on image")
byte_io = BytesIO()
image.save(byte_io, 'PNG')
Read more: http://fadeit.dk/blog/post/python3-flask-pil-in-memory-image
sth's solution didn't work for me
because in ...
Imaging/PIL/Image.pyc line 1423 ->
raise KeyError(ext) # unknown
extension
It was trying to detect the format from the extension in the filename , which doesn't exist in StringIO case
You can bypass the format detection by setting the format yourself in a parameter
import StringIO
output = StringIO.StringIO()
format = 'PNG' # or 'JPEG' or whatever you want
image.save(output, format)
contents = output.getvalue()
output.close()
save() can take a file-like object as well as a path, so you can use an in-memory buffer like a StringIO:
buf = StringIO.StringIO()
im.save(buf, format='JPEG')
jpeg = buf.getvalue()
With modern (as of mid-2017 Python 3.5 and Pillow 4.0):
StringIO no longer seems to work as it used to. The BytesIO class is the proper way to handle this. Pillow's save function expects a string as the first argument, and surprisingly doesn't see StringIO as such. The following is similar to older StringIO solutions, but with BytesIO in its place.
from io import BytesIO
from PIL import Image
image = Image.open("a_file.png")
faux_file = BytesIO()
image.save(faux_file, 'png')
When you say "I'd like to have number of such images stored in dictionary", it's not clear if this is an in-memory structure or not.
You don't need to do any of this to meek an image in memory. Just keep the image object in your dictionary.
If you're going to write your dictionary to a file, you might want to look at im.tostring() method and the Image.fromstring() function
http://effbot.org/imagingbook/image.htm
im.tostring() => string
Returns a string containing pixel
data, using the standard "raw"
encoder.
Image.fromstring(mode, size, data) =>
image
Creates an image memory from pixel
data in a string, using the standard
"raw" decoder.
The "format" (.jpeg, .png, etc.) only matters on disk when you are exchanging the files. If you're not exchanging files, format doesn't matter.

django's ImageField from post raw data

I'm sending a raw data array (RGBA8888) from an application (in C++) to a django server in the http's post data encoded in base64 like:
field1=value1&prof_img=KSsf134SF38u483y... more bytes ....sdknADdSIU7rb==
I've already managed to decode it back from base64 to raw data, I've made some tests and the data gets converted correctly.
Now i'm stuck trying to do something with this decoded data so I can save it in a model's ImageField.
How could I save the image back to a .png file, or any other image file format? (I don't need alpha/transparency)
You just need to save to disk the stream of bytes contained in the decoded base64 string. I got it working simply by just doing:
import base64
# assume 'x' is the variable where you have the base64 encoded image
# 'target.png' is the file name where you'll be saving it
# 'wb' is for a raw binary write operation
fout = open('target.png','wb')
# decode it and write it
fout.write(base64.b64decode(x))
# flush it
fout.flush()
Once you got it written in the disk, just add/edit the instance to the model in django with the file path.
That worked for me, hope it helps!
I'm pretty sure that you need PIL:
from PIL import Image
img_size = (500, 500)
img = Image.frombytes('RGB', img_size, raw_data)
img.save('mypic.png')
The rest will be Django job, right?

How to write PNG image to string with the PIL?

I have generated an image using PIL. How can I save it to a string in memory?
The Image.save() method requires a file.
I'd like to have several such images stored in dictionary.
You can use the BytesIO class to get a wrapper around strings that behaves like a file. The BytesIO object provides the same interface as a file, but saves the contents just in memory:
import io
with io.BytesIO() as output:
image.save(output, format="GIF")
contents = output.getvalue()
You have to explicitly specify the output format with the format parameter, otherwise PIL will raise an error when trying to automatically detect it.
If you loaded the image from a file it has a format property that contains the original file format, so in this case you can use format=image.format.
In old Python 2 versions before introduction of the io module you would have used the StringIO module instead.
For Python3 it is required to use BytesIO:
from io import BytesIO
from PIL import Image, ImageDraw
image = Image.new("RGB", (300, 50))
draw = ImageDraw.Draw(image)
draw.text((0, 0), "This text is drawn on image")
byte_io = BytesIO()
image.save(byte_io, 'PNG')
Read more: http://fadeit.dk/blog/post/python3-flask-pil-in-memory-image
sth's solution didn't work for me
because in ...
Imaging/PIL/Image.pyc line 1423 ->
raise KeyError(ext) # unknown
extension
It was trying to detect the format from the extension in the filename , which doesn't exist in StringIO case
You can bypass the format detection by setting the format yourself in a parameter
import StringIO
output = StringIO.StringIO()
format = 'PNG' # or 'JPEG' or whatever you want
image.save(output, format)
contents = output.getvalue()
output.close()
save() can take a file-like object as well as a path, so you can use an in-memory buffer like a StringIO:
buf = StringIO.StringIO()
im.save(buf, format='JPEG')
jpeg = buf.getvalue()
With modern (as of mid-2017 Python 3.5 and Pillow 4.0):
StringIO no longer seems to work as it used to. The BytesIO class is the proper way to handle this. Pillow's save function expects a string as the first argument, and surprisingly doesn't see StringIO as such. The following is similar to older StringIO solutions, but with BytesIO in its place.
from io import BytesIO
from PIL import Image
image = Image.open("a_file.png")
faux_file = BytesIO()
image.save(faux_file, 'png')
When you say "I'd like to have number of such images stored in dictionary", it's not clear if this is an in-memory structure or not.
You don't need to do any of this to meek an image in memory. Just keep the image object in your dictionary.
If you're going to write your dictionary to a file, you might want to look at im.tostring() method and the Image.fromstring() function
http://effbot.org/imagingbook/image.htm
im.tostring() => string
Returns a string containing pixel
data, using the standard "raw"
encoder.
Image.fromstring(mode, size, data) =>
image
Creates an image memory from pixel
data in a string, using the standard
"raw" decoder.
The "format" (.jpeg, .png, etc.) only matters on disk when you are exchanging the files. If you're not exchanging files, format doesn't matter.

Categories