issue while creating thumbnail in django - python

Code is like this:
class Document(models.Model):
docfile = models.FileField(upload_to='documents/big/')
thumbnail = models.FileField(upload_to='documents/small/')
def create_thumbnail(self):
if not self.image:
return
from PIL import Image
from cStringIO import StringIO
from django.core.files.uploadedfile import SimpleUploadedFile
import os
THUMBNAIL_SIZE = (200,200)
DJANGO_TYPE = self.image.file.content_type
if DJANGO_TYPE == 'image/jpeg':
PIL_TYPE = 'jpeg'
FILE_EXTENSION = 'jpg'
elif DJANGO_TYPE == 'image/png':
PIL_TYPE = 'png'
FILE_EXTENSION = 'png'
image = Image.open(StringIO(self.image.read()))
image.thumbnail(THUMBNAIL_SIZE, Image.ANTIALIAS)
temp_handle = StringIO()
image.save(temp_handle, PIL_TYPE)
temp_handle.seek(0)
suf = SimpleUploadedFile(os.path.split(self.image.name)[-1],
temp_handle.read(), content_type=DJANGO_TYPE)
self.thumbnail.save('%s_thumbnail.%s'%(os.path.splitext(suf.name)[0],FILE_EXTENSION), suf, save=False)
def save(self):
self.create_thumbnail()
super(ImageWithThumbnail, self).save()
Now I want to save the thumbnail image in documents/small/. But how to call this create_thumbnail function from view or model when uploading the image to create the thumbnail?

Did u mean you want to call the function in your views.
Then you can do
from urappname.models import Document
and call using
Document.create_thumbnail()

You can do this by overriding the default save() method of django.
For that, define this save() function under your model class as below:
def save(self, *args, **kwargs):
self.create_thumbnail()
super(Document, self).save(*args, **kwargs)

Related

Django HEIC to PNG conversion

I'm trying to convert heic to png, which I successfully achieved in Python with the help of Wand library. I also saved the file locally to see, if the convertion worked, and it did. The problem is that Django's serializer cant take in Wand image, and I have to convert it to InMemoryUploadedFile. Whatever I do, I still can't make the serializator to take in the converted image.
views.py update_post()
#api_view(['PUT'])
#permission_classes([IsAuthenticated])
def update_post(request, id):
image = request.FILES['image']
print(image.size, image.name, image.file,
image.content_type, image.field_name)
if image.content_type == 'image/heif':
img = Image(file=image)
img.format = 'png'
img_io = io.BytesIO()
img.save(file=img_io)
filename = image.name.replace('.heic', '.png')
img.save(filename=filename)
img_file = InMemoryUploadedFile(
img_io,
'image',
filename,
'image/png',
sys.getsizeof(img_io),
None)
print(img_file.size, img_file.name, img_file.file,
img_file.content_type, img_file.field_name)
image = img_file
#request.data['image'] = img_file
#request.FILES['image'] = img_file
# data = request.data
# print(img_file, image)
loggedin_user = request.user.username
post = Post.objects.get(id=id)
post_user = post.user
if (str(post_user) == str(loggedin_user)):
serializer = PostSerializer(
instance=post, data={'caption': request.data['caption'], 'image': image})
if serializer.is_valid():
print(serializer.validated_data)
serializer.save()
else:
print('achjo')
print(serializer.data)
return Response(status=status.HTTP_200_OK)

How to work with uploaded file using Django

I have Optical Character Recognition (OCR) project. I am generating an API using Django Framework. The API should look like as below:
{
"id": 1,
"title": "PDF Title",
"input": "input.pdf",
"output": "output.pdf"
}
My models.py file as below:
from django.db import models
from .create_pdf_output import *
# Create your models here.
class Document(models.Model):
title = models.CharField(max_length=255)
pdf_input = models.FileField(upload_to='documents/inputs', max_length=200, blank=False)
pdf_output = models.FileField(upload_to='documents/outputs', max_length=200, blank=True)
def save(self):
self.pdf_output = create_pdf_output(self.pdf_input)
super(Document, self).save()
def __str__(self):
return self.title
In models.py file I call create_pdf_file.py which should perform OCR operations on pdf input
create_pdf_output.py
import shutil
import cv2
import numpy as np
import img2pdf
from pdf2image import convert_from_path
import os
def create_pdf_output(pdf_input):
pdf = str(pdf_input)
pdf_name = os.path.splitext(pdf)[0] + "_out.pdf"
pages = convert_from_path(pdf_input, 500)
if not os.path.exists('images'):
os.mkdir('images')
for ind, page in enumerate(pages):
page.save(f'images/out{ind}.jpg', 'JPEG')
for ind, img in enumerate(os.listdir('images')):
img_rgb = cv2.imread(os.path.join('images', img))
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('templates.jpg', 0)
w, h = template.shape[::-1]
res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
threshold = 0.8
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1]):
cropped_image = img_rgb[pt[1]:pt[1]+h, pt[0]:pt[0]+ 4*h]
blurred = cv2.blur(cropped_image, (50,50))
img_rgb[pt[1]:pt[1]+h, pt[0]:pt[0]+ 4*h] = blurred
if not os.path.exists('results'):
os.mkdir('results')
cv2.imwrite(f'results/res{ind}.jpg', img_rgb)
dirname = 'images'
with open(pdf_name, 'wb') as f:
imgs = []
for fname in os.listdir(dirname):
if not fname.endswith('.jpg'):
continue
path = os.path.join(dirname, fname)
if os.path.isdir(path):
continue
imgs.append(path)
f.write(img2pdf.convert(imgs))
shutil.rmtree('images')
shutil.rmtree('results')
return pdf_name
However, since create_input_output function takes FieldFile as input it generates an error as below.
expected str, bytes or os.PathLike object, not FieldFile
My question is how can I work with input file, so I can generate output pdf file?
views.py
# pdf api
class OcrPDfDataApiView(APIView):
parser_class = [MultiPartParser,]
def post(self, request, format=None):
if 'data' not in request.data:
raise ParseError("Empty content")
filename = "whatever.pdf" # received file name
file_obj = request.data['data']
with default_storage.open('tmp/'+filename, 'wb+') as destination:
for chunk in file_obj.chunks():
destination.write(chunk)
dirName = os.path.dirname(__file__)
cwd = Path.cwd()
filename = os.path.join(cwd, 'media','tmp','whatever.pdf')
texts = print_pages(filename)
return Response(texts)
utils.py
import pytesseract
from PIL import Image
from PIL import ImageFilter
import requests
import docx2txt
import pdf2image
import PyPDF2
import pyttsx3
import os
import io
def print_pages(pdf_file):
images = pdf2image.convert_from_path(pdf_file)
for pages,img in enumerate(images):
text = pytesseract.image_to_string(img)
print(text)
return text

Testing an ImageField in DRF

I am using Django Imagekit in models.py:
from imagekit.models import ProcessedImageField
class AltroUser(models.Model):
first_name = models.CharField(_('first name'), max_length=30)
image = ProcessedImageField(upload_to='media/path',
default='user_default.jpg',
processors=[ResizeToFill(640, 640)],
format='JPEG',
options={'quality': 60})
serializers.py:
class UserRegistrationSerializer(Serializer):
first_name = serializers.CharField()
image = serializers.ImageField()
I am trying to test the image field. I have tried following methods:
def get_test_image():
try:
image = DjangoFile(open(os.path.join(django_settings.MEDIA_ROOT, 'user_default.jpg'),
mode='rb'))
return image
except (OSError, IOError) as e:
return None
def get_test_image1():
file = io.BytesIO()
image = Image.new('RGBA', size=(100, 100), color=(155, 0, 0))
image.save(file, 'png')
file.name = 'test.png'
file.seek(0)
return SimpleUploadedFile('abc.jpg', file.read())
def get_test_image2():
path = os.path.join(django_settings.MEDIA_ROOT, 'user_default.jpg')
file = File(open(path, 'r+b'))
return SimpleUploadedFile('abc.jpg', file.read())
I have tried calling the above three methods to set the value of the image key but none of them worked.
For get_test_image(), I get a response "The submitted file is empty."
For get_test_image1() and get_test_image2(), I get a response "The submitted file is empty." with an exception before in the data image field '_io.BytesIO' object has no attribute 'encoding'.
I don't understand what am I missing. Please help.
Here's an example of what I'm using to generate test image:
from StringIO import StringIO
from PIL import Image
from django.core.files import File
def get_image_file(name='test.png', ext='png', size=(50, 50), color=(256, 0, 0)):
file_obj = StringIO()
image = Image.new("RGBA", size=size, color=color)
image.save(file_obj, ext)
file_obj.seek(0)
return File(file_obj, name=name)
In Pillow==8.3.1, using StringIO() gave me this error:
TypeError: string argument expected, got 'bytes'.
I used BytesIO() instead and it worked like a charm
from io import BytesIO
def get_image_file(
self, name="test.png", ext="png", size=(50, 50), color=(256, 0, 0)
):
file_obj = BytesIO()
image = Image.new("RGBA", size=size, color=color)
image.save(file_obj, ext)
file_obj.seek(0)
return File(file_obj, name=name)

Thumbnail for ImageField in django model, override save

I am trying to create a thumbnail from ImageField and save it to my model. I am using this as reference: http://www.yilmazhuseyin.com/blog/dev/create-thumbnails-imagefield-django/
Files are created correctly, I get no errors but fields are not saved in model.
I think i could messed things up in save method. What am I doing wrong?
Here is my code:
def get_avatar_path(instance, filename):
# file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
return 'avatars/{0}/{1}'.format(instance.id, filename)
class User(AbstractUser):
# First Name and Last Name do not cover name patterns
# around the globe.
name = models.CharField(_('Name of User'), blank=True, max_length=255)
avatar = models.ImageField(upload_to=get_avatar_path, blank=True)
small_avatar = models.ImageField(upload_to=get_avatar_path,
blank=True)
def create_thumbnail(self):
# If there is no image associated with this.
# do not create thumbnail
if not self.avatar:
return
# Set our max thumbnail size in a tuple (max width, max height)
THUMBNAIL_SIZE = (200, 200)
DJANGO_TYPE = self.avatar.file.content_type
print DJANGO_TYPE
if DJANGO_TYPE == 'image/jpeg':
PIL_TYPE = 'jpeg'
FILE_EXTENSION = 'jpg'
elif DJANGO_TYPE == 'image/png':
PIL_TYPE = 'png'
FILE_EXTENSION = 'png'
elif DJANGO_TYPE == 'image/gif':
PIL_TYPE = 'gif'
FILE_EXTENSION = 'gif'
# Open original photo which we want to thumbnail using PIL's Image
image = Image.open(StringIO(self.avatar.read()))
# use our PIL Image object to create the thumbnail, which already
image.thumbnail(THUMBNAIL_SIZE, Image.ANTIALIAS)
# Save the thumbnail
temp_handle = StringIO()
image.save(temp_handle, PIL_TYPE)
temp_handle.seek(0)
# Save image to a SimpleUploadedFile which can be saved into ImageField
print os.path.split(self.avatar.name)[-1]
suf = SimpleUploadedFile(os.path.split(self.avatar.name)[-1],
temp_handle.read(), content_type=DJANGO_TYPE)
# Save SimpleUploadedFile into image field
print os.path.splitext(suf.name)[0]
self.small_avatar.save(
'%s_thumbnail.%s' % (os.path.splitext(suf.name)[0], FILE_EXTENSION),
suf, save=False)
def save(self, *args, **kwargs):
self.create_thumbnail()
super(User, self).save()
Thanks for feedback. Sorry for newbie problems, I am a beginner developer.
Problem seems to be resolved by invalidating caches, restarting IDE and services.
In my opinion code above should be persisted as some of solutions on the web are outdated.

Django create thumbnail with PIL when i upload image

I use django-dropbox for the image storage on my website.
When i upload the image i want to automatically create an thumbnail and save it.
I tryed different methods but with no success
Any help will be apreciated
I get this exception error:
cannot identify image file
Here is the code:
class Product(models.Model):
image = models.ImageField(upload_to='images', storage=STORAGE, null=True, blank=True)
thumb = models.ImageField(upload_to='thumbs', storage=STORAGE, null=True, blank=True)
def __unicode__(self):
return "%s,%s" %(self.id,self.title)
def save(self):
# create a thumbnail
self.create_thumbnail()
super(Product, self).save()
def create_thumbnail(self):
# create a thumbnail
#self.create_thumbnail()
from PIL import Image
from cStringIO import StringIO
from django.core.files.uploadedfile import SimpleUploadedFile
import os
try:
DJANGO_TYPE = self.image.file.content_type
print DJANGO_TYPE
if DJANGO_TYPE == 'image/jpeg':
PIL_TYPE = 'jpeg'
FILE_EXTENSION = 'jpg'
elif DJANGO_TYPE == 'image/png':
PIL_TYPE = 'png'
FILE_EXTENSION = 'png'
else:
print error
print "Working1"
print StringIO(self.image.read())
im = Image.open(StringIO(self.image.read()))
size = 128, 128
im.thumbnail(size, Image.ANTIALIAS)
# Save the thumbnail
print "Working2"
temp_handle = StringIO()
im.save(temp_handle, PIL_TYPE)
temp_handle.seek(0)
# Save image to a SimpleUploadedFile which can be saved into
# ImageField
print "Working3"
suf = SimpleUploadedFile(os.path.split(self.image.name)[-1],
temp_handle.read(), content_type=DJANGO_TYPE)
# Save SimpleUploadedFile into image field
self.thumb.save('%s_thumbnail.%s'%(os.path.splitext(suf.name)[0],FILE_EXTENSION), suf, save=True)
print "Working4"
except Exception as e:
print e

Categories