I want to use PIL function Image.open(), but it only works if I pass the image path as an argument. I have to find a way to get this image path. I'm using widget='image' and odoo 8
The images are stored in database, base64 encoded. You will have to save them to a file yourself.
import tempfile
import base64
import os
from PIL import Image
from openerp import models, fields, api
from openerp.exceptions import UserError
class MyModel(models.Model):
[...]
image = fields.Binary()
#api.multi
def open_image(self):
self.ensure_one()
if not self.image:
raise UserError("no image on this record")
# decode the base64 encoded data
data = base64.decodestring(self.image)
# create a temporary file, and save the image
fobj = tempfile.NamedTemporaryFile(delete=False)
fname = fobj.name
fobj.write(data)
fobj.close()
# open the image with PIL
try:
image = Image.open(fname)
# do stuff here
finally:
# delete the file when done
os.unlink(fname)
Related
I am using pypng and pyqrcode for QR code image generation in django app.
import os
from pyqrcode import create
import png # pypng
import base64
def embed_QR(url_input, name):
embedded_qr = create(url_input)
embedded_qr.png(name, scale=7)
def getQrWithURL(url):
name = 'url.png'
embed_QR(url, name)
with open(name, "rb") as image_file:
image_data = base64.b64encode(image_file.read()).decode('utf-8')
return image_data
When I call getQrWithURL with a url, it produces a file url.png to my directory. Is there a way to only get the image data without producing a file output?
thanks for your help.
Use a BytesIO as a writable stream:
import io
# Make a writeable stream
buffer = io.BytesIO()
# Create QR and write to buffer
embedded_qr = create(url_input)
embedded_qr.png(buffer,scale=7)
# Extract buffer contents - this is what you would get by reading a PNG disk file but without creating it
PNG = buffer.getvalue()
Your variable PNG now contains this:
b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\xe7\x00\x00\x00\xe7\x01\x00\x00\x00\x00\xcd\x8f|\x8d\x00\x00\x01CIDATx\x9c\xed\x971\x92\x830\x0cE\xc5PPr\x04\x8e\x92\xa3\xc1\xd1|\x14\x8e\x90\x92\x82\xb1V_2\t\xde\xb0;i?c\x15q\xecG\xf3\x91\xfc%D\xff\x89,\x8d6\xda\xe8\x97\xf4)\x88AW\xfb\xed\xb7Q\x93\xef\'fj\x7ft\x1f\x9e\xf2Xt\xb7\xe34\x97Cb\x9a\xa43\x8a\xe3XL\xfd-\xa8\xc8\x1c\x19\xbc\x11-\xbb\x1b\xd0\xa3&m\x11\xe8\xbd\xaeX"\x1a\xbe\x01\xa1Q\x9aW\xaeBE\x8fXe\xee\xf4\x1c\xc44\xcd\x19\n\x93dX\xfcc\xb1\xcd\xc8L\x91A\x08\xb5c\xd5\xcd\x1f\xea\xb7*\xbfl\xd4\xf4\x9ao\xb8\xdeB\xbb\xd3-c\xa4h\xbc\x9dn\xa3\xd5\xa4\t\x1dW\xdf\t5\x9dt\xb1b,N\x88\xc8}\xe5\x93t\xd4\x8aQ\xa1Pp\xbd\x06\xe43\x9f\x9d\x90\x90\xfa-\xdb\xa3\xe3b\xa2\xc0Rw+6\n\',U\x18S\xdfo\xdf\xa0\xa3\x18\xf70J\xac\xf2\xea\xc6\xf5\xdb\xa0\xa3%\xdc>"\x91R\xbd\r>z\xccHq\xcb|T\xba\x98\xfa\xa8\xe8G1J\xcfN\xfd[\xc3/[x\xbbQ\x04=\x8d\xfek\x16\xafn\xf1\xfc\x14m\x18BK\xef\x9a\xa8\xa9\xd7\xa4\'\xed\xfd\x902\xd3\xf0\r\x8c\x12z\xb4\xe1\x0fW\xa1\xa2\x7fF\xa3\x8d6\xfa\x15\xfd\x01\xb9MCH#\xc3\xa2\x96\x00\x00\x00\x00IEND\xaeB`\x82'
I'm working with Django in Python 3, and I have a model with an ImageField and I'm trying to override the .save() to do tiff to jpeg conversion:
from PIL import Image
from io import BytesIO
from django.core.files.base import ContentFile
class MyModel(models.Model):
image = models.ImageField(upload_to=upload_image_to, editable=True, null=True, blank=True)
def save(self, *args, **kwargs):
pil_image_obj = Image.open(self.image)
new_image_io = BytesIO()
rgb_pil_image_obj = pil_image_obj.convert("RGB")
rgb_pil_image_obj.save(new_image_io, quality=90, format='JPEG')
# temp_name = self.image.name
# self.image.delete(save=False)
# self.image.save(
# temp_name,
# content=ContentFile(new_image_io.getvalue()),
# save=False
# )
super().save(*args, **kwargs)
However, this leads to:
tempfile.tif: Cannot read TIFF header.
*** OSError: -2
If I try the save experiment but only opening the TIFF file from disk instead of feeding PIL.Image with the Django InMemoryUploadedFile, then everything works absolutely fine and the tiff is converted to a jpeg.
Also pil_image_obj.verify() doesn't throw any exceptions.
I'm using Pillow==5.3.0
What could be the issue? And is there any other way to do such a conversion?
You need to pass the path of the image file to Image.open(). Currently you're passing the field itself.
pil_image_obj = Image.open(self.image.path) # Pass the path
Im doing an application that uses Django in server-side.
Im trying to do that:
import uuid
from base64 import b64decode
from django.core.files.base import ContentFile
#staticmethod
def add_photo(user, person, image_base64):
photo = DatabasePersonPhoto()
photo.user = user
photo.person = person
image_data = b64decode(image_base64)
image_name = str(uuid.uuid4())+".jpg"
photo.image = ContentFile(image_data, image_name)
photo.save()
return photo
This is my Base64 String:
data:image/jpeg;base64,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
The image file is generated, but I cant open it like an image.
I think this will be a best approach tried it and tested in django 1.10. based on this SO answer: https://stackoverflow.com/a/28036805/6143656
I made a function for decoded base64 file.
def decode_base64_file(data):
def get_file_extension(file_name, decoded_file):
import imghdr
extension = imghdr.what(file_name, decoded_file)
extension = "jpg" if extension == "jpeg" else extension
return extension
from django.core.files.base import ContentFile
import base64
import six
import uuid
# Check if this is a base64 string
if isinstance(data, six.string_types):
# Check if the base64 string is in the "data:" format
if 'data:' in data and ';base64,' in data:
# Break out the header from the base64 content
header, data = data.split(';base64,')
# Try to decode the file. Return validation error if it fails.
try:
decoded_file = base64.b64decode(data)
except TypeError:
TypeError('invalid_image')
# Generate file name:
file_name = str(uuid.uuid4())[:12] # 12 characters are more than enough.
# Get the file name extension:
file_extension = get_file_extension(file_name, decoded_file)
complete_file_name = "%s.%s" % (file_name, file_extension, )
return ContentFile(decoded_file, name=complete_file_name)
Then you can call the function
import decode_base64_file
p = Post(content='My Picture', image=decode_based64_file(your_base64_file))
p.save()
I found the solution.
I need to use only the parte without data:image/jpeg;base64,
In Python, we can do it with something like this:
image_base64 = image_base64.split('base64,', 1 )
fh = open("imageToSave.png", "wb")
fh.write(imgData.decode('base64'))
fh.close()
Edit (klaus-d): The code above gives an example, how to store an image file from BASE64 encoded data. It opens a file imageToSave.png in binary mode for writing, then decodes the base64 image data and write the result to the file. At the end it closes the file descriptor.
I'm fairly new to Python. Currently I'm making a prototype that takes an image, creates a thumbnail out of it and and uploads it to the ftp server.
So far I got the get image, convert and resize part ready.
The problem I run into is that using the PIL (pillow) Image library converts the image is a different type than that can be used when uploading using storebinary()
I already tried some approaches like using StringIO or BufferIO to save the image in-memory. But I'm getting errors all the time. Sometimes the image does get uploaded but the file appears to be empty (0 bytes).
Here is the code I'm working with:
import os
import io
import StringIO
import rawpy
import imageio
import Image
import ftplib
# connection part is working
ftp = ftplib.FTP('bananas.com')
ftp.login(user="banana", passwd="bananas")
ftp.cwd("/public_html/upload")
def convert_raw():
files = os.listdir("/home/pi/Desktop/photos")
for file in files:
if file.endswith(".NEF") or file.endswith(".CR2"):
raw = rawpy.imread(file)
rgb = raw.postprocess()
im = Image.fromarray(rgb)
size = 1000, 1000
im.thumbnail(size)
ftp.storbinary('STOR Obama.jpg', img)
temp.close()
ftp.quit()
convert_raw()
What I tried:
temp = StringIO.StringIO
im.save(temp, format="png")
img = im.tostring()
temp.seek(0)
imgObj = temp.getvalue()
The error I'm getting lies on the line ftp.storbinary('STOR Obama.jpg', img).
Message:
buf = fp.read(blocksize)
attributeError: 'str' object has no attribute read
For Python 3.x use BytesIO instead of StringIO:
temp = BytesIO()
im.save(temp, format="png")
ftp.storbinary('STOR Obama.jpg', temp.getvalue())
Do not pass a string to storbinary. You should pass a file or file object (memory-mapped file) to it instead. Also, this line should be temp = StringIO.StringIO(). So:
temp = StringIO.StringIO() # this is a file object
im.save(temp, format="png") # save the content to temp
ftp.storbinary('STOR Obama.jpg', temp) # upload temp
I store uploaded images in gridfs (mongodb). Therefore, the image data is never saved on the normal filesystem. This works by using the following code:
import pymongo
import gridfs
conn = pymongo.Connection()
db = conn.my_gridfs_db
fs = gridfs.GridFS(db)
...
with fs.new_file(
filename = 'my-filename-1.png',
) as fp:
fp.write(image_data_as_string)
I also want to store thumbnails of that image. I do not care which library to use, PIL, Pillow, sorl-thumbnail or whatever fits best will work for me.
I want to know if there is a way to generate thumbnails without temporarily saving the file in the filesystem. That would be much cleaner and less overhead. Is there an in-memory thumbnail generator?
Update
My solution to save the thumbnail:
from PIL import Image, ImageOps
content = cStringIO.StringIO()
content(icon)
image = Image.open(content)
temp_content = cStringIO.StringIO()
thumb = ImageOps.fit(image, (width, height), Image.ANTIALIAS)
thumb.save(temp_content, format='png')
temp_content.seek(0)
gridfs_image_data = temp_content.getvalue()
with fs.new_file(
content_type = mimetypes.guess_type(filename)[0],
filename = filename,
size = size,
width = width,
height = height,
) as fp:
fp.write(gridfs_image_data)
The file is then served via nginx-gridfs.
You can save it to a StringIO object instead of a file (use the cStringIO module, if possible):
from StringIO import StringIO
fake_file = StringIO()
thing.save(fake_file) # Acts like a file handle
contents = fake_file.getvalue()
fake_file.close()
Or if you like context managers:
import contextlib
from StringIO import StringIO
with contextlib.closing(StringIO()) as handle:
thing.save(handle)
contents = handle.getvalue()