django-ckeditor files upload other than image - python

Iam using django-ckeditor.
Iam uploading image files and .swf files in image and flash upload icons. But when i upload files other than these, Iam getting error as "cannot identify image file". For swf files , thumbnail is not creating and dummy image is showing without any url.
My views in ckeditor as :
#csrf_exempt
def upload(request):
upload = request.FILES['upload']
upload_ext = os.path.splitext(upload.name)[1]
upload_filename = get_upload_filename(upload.name, request.user)
out = open(upload_filename, 'wb+')
for chunk in upload.chunks():
out.write(chunk)
out.close()
if upload_ext != ".swf":
create_thumbnail(upload_filename)
url = get_media_url(upload_filename)
url = url.replace("\\", "/")
return HttpResponse("""
<script type='text/javascript'>
window.parent.CKEDITOR.tools.callFunction(%s, '%s');
</script>""" % (request.GET['CKEditorFuncNum'], url))
thumbnail,
def create_thumbnail(filename):
image = Image.open(filename)
if image.mode not in ('L', 'RGB'):
image = image.convert('RGB')
imagefit = ImageOps.fit(image, THUMBNAIL_SIZE, Image.ANTIALIAS)
imagefit.save(get_thumb_filename(filename))
Anyone help me to solve this issue..

Technically, only image files can have thumbnails. All other types should have default thumbnails based on the their types(may be icon image). In your code, the logic should
if upload_ext in [".jpg", ".png",]:
create_thumbnail(filename)
else:
create_default_thumbnail(upload_ext) // for .swf, .doc etc

Related

Image processing after upload with Python Bottle

Context
I have made a simple web app for uploading content to a blog. The front sends AJAX requests (using FormData) to the backend which is Bottle running on Python 3.7. Text content is saved to a MySQL database and images are saved to a folder on the server. Everything works fine.
Image processing and PIL/Pillow
Now, I want to enable processing of uploaded images to standardise them (I need them all resized and/or cropped to 700x400px).
I was hoping to use Pillow for this. My problem is creating a PIL Image object from the file object in Bottle. I cannot initialise a valid Image object.
Code
# AJAX sends request to this route
#post('/update')
def update():
# Form data
title = request.forms.get("title")
body = request.forms.get("body")
image = request.forms.get("image")
author = request.forms.get("author")
# Image upload
file = request.files.get("file")
if file:
extension = file.filename.split(".")[-1]
if extension not in ('png', 'jpg', 'jpeg'):
return {"result" : 0, "message": "File Format Error"}
save_path = "my/save/path"
file.save(save_path)
The problem
This all works as expected, but I cannot create a valid Image object with pillow for processing. I even tried reloading the saved image using the save path but this did not work either.
Other attempts
The code below did not work. It caused an internal server error, though I am having trouble setting up more detailed Python debugging.
path = save_path + "/" + file.filename
image_data = open(path, "rb")
image = Image.open(image_data)
When logged manually, the path is a valid relative URL ("../domain-folder/images") and I have checked that I am definitely importing PIL (Pillow) correctly using PIL.PILLOW_VERSION.
I tried adapting this answer:
image = Image.frombytes('RGBA', (128,128), image_data, 'raw')
However, I won’t know the size until I have created the Image object. I also tried using io:
image = Image.open(io.BytesIO(image_data))
This did not work either. In each case, it is only the line trying to initialise the Image object that causes problems.
Summary
The Bottle documentation says the uploaded file is a file-like object, but I am not having much success in creating an Image object that I can process.
How should I go about this? I do not have a preference about processing before or after saving. I am comfortable with the processing, it is initialising the Image object that is causing the problem.
Edit - Solution
I got this to work by adapting the answer from eatmeimadanish. I had to use a io.BytesIO object to save the file from Bottle, then load it with Pillow from there. After processing, it could be saved in the usual way.
obj = io.BytesIO()
file.save(obj) # This saves the file retrieved by Bottle to the BytesIO object
path = save_path + "/" + file.filename
# Image processing
im = Image.open(obj) # Reopen the object with PIL
im = im.resize((700,400))
im.save(path, optimize=True)
I found this from the Pillow documentation about a different function that may also be of use.
PIL.Image.frombuffer(mode, size, data, decoder_name='raw', *args)
Note that this function decodes pixel data only, not entire images.
If you have an entire image file in a string, wrap it in a BytesIO object, and use open() to load it.
Use StringIO instead.
From PIL import Image
try:
import cStringIO as StringIO
except ImportError:
import StringIO
s = StringIO.StringIO()
#save your in memory file to this instead of a regular file
file = request.files.get("file")
if file:
extension = file.filename.split(".")[-1]
if extension not in ('png', 'jpg', 'jpeg'):
return {"result" : 0, "message": "File Format Error"}
file.save(s)
im = Image.open(s)
im.resize((700,400))
im.save(s, 'png', optimize=True)
s64 = base64.b64encode(s.getvalue())
From what I understand, you're trying to resize the image after it has been saved locally (note that you could try to do the resize before it is saved). If this is what you want to achieve here, you can open the image directly using Pillow, it does the job for you (you do not have to open(path, "rb"):
image = Image.open(path)
image.resize((700,400)).save(path)

How to generate barcode in python as response of image object

Views.py:
def Bar(request):
payload = json.loads(request.body.decode('utf-8'))
a=payload["donor_n_key"]
ean = barcode.get('code128', a, writer=ImageWriter())
filename = ean.save('ean13')
image = ean.render()
return HttpResponse(image,content_type="image/png")
Here i have downloaded the barcode image but I am unable to open that image.I am getting the error is windows photo viewer can't open this picture because either photo viewer does not support this file format.
I am new to this django restframework.Please help me Anyone.
In Your View.py
Import This
import barcode
from barcode.writer import ImageWriter
def Bar(request):
lineCode = '1234567891234'
barCodeImage = barcode.get('ean13', lineCode, writer=ImageWriter())
filename = barCodeImage.save(item_name.png)
return HttpResponse(image,content_type="image/png")
It Will Generates Image and save it your project root folder
More help visit this link PyBarcode

Return PNG image from Django views is damaged

I'm working on a Django(2) project in which I need to return a PNG image as HttpResponse when I return this image in the form of a zip archive it returns the image correctly, but when I return the PNG image directly it damaged the image.
Here's my code:
How it's writing the image:
img_resized = cv2.resize(seg_image, dsize)
cv2.imwrite(os.path.join(settings.BASE_DIR, 'img/MaskedImage.png'), img_resized)
How it's returning the Image:
response = HttpResponse(os.path.join(settings.BASE_DIR, 'img/MaskedImage.png'), content_type='image/png')
response['Content-Disposition'] = 'attachment; filename=MaskedImage.png'
return response
It returns an Image with the name MaskedImage.pn but the image is damaged, not able to open.
What can be wrong here?
Thanks in advance!
You will need to read the image data. You're currently returning a response with just the image path.
with open(os.path.join(settings.BASE_DIR, 'img/MaskedImage.png'), 'rb') as fp:
response = HttpResponse(fp.read(), content_type='image/png')
response['Content-Disposition'] = 'attachment; filename=MaskedImage.png'
return response

Pillow Resizing images (thumbnail) on Amazon S3 - Django

I am try resize an image when this is saved.
Specifically, my images are stored on Amazon S3, then I use the django-storages and boto3 third party applications
When a image is saved, this is stored in my Amazon S3 bucket, having a acces url such as follow:
https://s3-sa-east-1.amazonaws.com/ihost-project/media/studyoffer_images/algoritmos-para-ensenanza/15061122523583.jpg
The code to save and resize the image is this:
class UploadStudyOffer(models.Model):
study_offer = models.ForeignKey(StudiesOffert, related_name='uploadsstudyoffer')
image = models.ImageField(upload_to=get_image_path)
# images folder per object
def save(self, *args, **kwargs):
super(UploadStudyOffer, self).save(*args, **kwargs)
# We first check to make sure an image exists
if self.image:
# Open image and check their size
image = Image.open(self.image)
i_width, i_height = image.size
max_size = (100,100)
# We resize the image if it's too large
if i_width > 1000:
image.thumbnail(max_size, Image.ANTIALIAS)
image.save(self.image.path)
When I upload an image, I get this message:
Exception Type: NotImplementedError at /host/study-offer/algoritmos-para-ensenanza/edit/images/
Exception Value: This backend doesn't support absolute paths.
And I am not sure, if the error is manage at storages or boto backends or in Pillow.
Then at level of Pillow I found the following options in the moment of save the image, such as follow:
I change the section code:
image.save(self.image.path)
to:
image.save(self.image.name)
And I get this error:
File "/home/bgarcial/workspace/hostayni_platform/hosts/models.py" in save
542. image.save(self.image.name) #[Errno 2] No such file or directory: 'studyoffer_images/ingenieria-de-sistemas/15061122523583.jpg'
File "/home/bgarcial/.virtualenvs/hostayni/lib/python3.6/site-packages/PIL/Image.py" in save
1725. fp = builtins.open(filename, "w+b")
Exception Type: FileNotFoundError at /host/study-offer/algoritmos-para-ensenanza/edit/images/
Exception Value: [Errno 2] No such file or directory: 'studyoffer_images/algoritmos-para-ensenanza/1900-X-1080-Wallpapers-022.jpg'
Of course, my image is stored om Amazon S3 and not locally in my project or hard disk, then I use the url parameter of this way:
I change
image.save(self.image.name)
to
image.save(self.image.url)
And I get this error:
Exception Type: FileNotFoundError at /host/study-offer/algoritmos-para-ensenanza/edit/images/
Exception Value: [Errno 2] No such file or directory: 'https://s3-sa-east-1.amazonaws.com/ihost-project/media/studyoffer_images/algoritmos-para-ensenanza/15061122523583.jpg'
Getting the amazon s3 image URL does not works, even though the url is a valid url https://s3-sa-east-1.amazonaws.com/ihost-project/media/studyoffer_images/algoritmos-para-ensenanza/15061122523583.jpg
Then I change
image.save(self.image.url)
to:
image.save(self.image.file)
And my image is uploaded without any errors, but is not resized and is uploaded as its original format.
How to can I process a image uploaded from my application and their result was saved on Amazon S3 to after use them?
Fairly new to Django/Python, but this is how I solved it. Save large file to AWS, open it with Pillow, then resize and save in memory. Then push to AWS using default_storage just as the django-storages help docs suggest. Note that img.thumbnail will retain aspect with just the longer edge of the image set to 1000 pixels. image is the Django model ImageField.
from django.core.files.storage import default_storage
from io import BytesIO
..
def save(self, *args, **kwargs):
#run save of parent class above to save original image to disk
super().save(*args, **kwargs)
memfile = BytesIO()
img = Image.open(self.image)
if img.height > 1000 or img.width > 1000:
output_size = (1000, 1000)
img.thumbnail(output_size, Image.ANTIALIAS)
img.save(memfile, 'JPEG', quality=95)
default_storage.save(self.image.name, memfile)
memfile.close()
img.close()
You can make it easier and use easy_thumbnails app.
If you want to crop the image on save then you can do it with:
from easy_thumbnails.fields import ThumbnailerImageField
CROP_SETTINGS = {'size': (1000, 500), 'crop': 'smart'}
class UploadStudyOffer(models.Model):
image =ThumbnailerImageField(upload_to=get_image_path,
resize_source=CROP_SETTINGS)
Or you can manually specify the size of the image in the template:
{% load thumbnail %}
<img src="{% thumbnail offer.image 1000x500 crop %}" alt="" />
Most of what I found online suggested removing the Pillow resize and writing an AWS Lambda function to handle the resize on upload. I initially tried that approach, but according to the AWS docs you shouldn’t use the same bucket for input and output, meaning I had to create a second S3 bucket just for resized images. I couldn’t figure out how to get that setup working with django-storages.
A second approach I found mentioned using a buffer to save the resized image into, and then saving that to AWS. The examples of this that I found were either incomplete or used old versions of python. Here is what actually worked for me.
user/models.py
from app.utils import image_resize
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default="profile-default.png",
upload_to="profile_pics")
def __str__(self):
return f"{self.user.username} Profile"
def save(self, *args, **kwargs):
image_resize(self.image, 512, 512)
super().save(*args, **kwargs)
app/utils.py
from django.core.files import File
from pathlib import Path
from PIL import Image
from io import BytesIO
image_types = {
"jpg": "JPEG",
"jpeg": "JPEG",
"png": "PNG",
"gif": "GIF",
"tif": "TIFF",
"tiff": "TIFF",
}
def image_resize(image, width, height):
# Open the image using Pillow
img = Image.open(image)
# check if either the width or height is greater than the max
if img.width > width or img.height > height:
output_size = (width, height)
# Create a new resized “thumbnail” version of the image with Pillow
img.thumbnail(output_size)
# Find the file name of the image
img_filename = Path(image.file.name).name
# Spilt the filename on “.” to get the file extension only
img_suffix = Path(image.file.name).name.split(".")[-1]
# Use the file extension to determine the file type from the image_types dictionary
img_format = image_types[img_suffix]
# Save the resized image into the buffer, noting the correct file type
buffer = BytesIO()
img.save(buffer, format=img_format)
# Wrap the buffer in File object
file_object = File(buffer)
# Save the new resized file as usual, which will save to S3 using django-storages
image.save(img_filename, file_object)
I’m overriding the save method still, and calling a function I’ve placed in utils.py of my main application. The following happens in the image_resize function:
The image_function checks if the image is too wide or tall and, if it is, saves a resized version first to a memory buffer and then to S3. Back in the save method we call super().save() to save the remaining fields. The super().save() needs to be called after the image.save() or both the original and the resized images will get uploaded to S3.
I hope that was helpful to someone.
You can Visit https://blog.soards.me/posts/resize-image-on-save-in-django-before-sending-to-amazon-s3/ for more details

Rotate image uploaded via email using PIL for Django website

My website allows users to upload photos to their gallery via email and it works perfectly. However, photos taken on the iPhone in portrait mode do NOT rotate correctly. I would like to rotate the photo using PIL during the "mail filtering" process. Here is the code that I am using to successfully retrieve the image from the email and save to my Django model
image = ContentFile(b64decode(part.get_payload()))
img = Photo(user=user)
filename = part.get_filename().lower()
img.img.save(filename, image)
img.save()
*Updated code that successfully rotates temp image to local dir *
image = ContentFile(b64decode(part.get_payload()))
im = Image.open(image)
tempfile = im.rotate(90)
tempfile.save("/srv/www/mysite.com/public_html/media/images/rotate.jpg", "JPEG")
img = Photo(user=user)
img.img.save('rotate.jpg', tempfile)
img.save()
Now, I'm trying to take the "temp image" and save it to my model. Unfortunately, it is not saving. Any suggestions would be greatly appreciated.
http://effbot.org/imagingbook/image.htm
clearly states that rotate() returns an new image instance.
There is nothing in the documentation about in-place operations. Or?

Categories

Resources