Django HEIC to PNG conversion - python

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)

Related

uploading and saving base64 image data to a Django image field in django rest framework

I'm having trouble saving base64 image data to a django image field, this is what i have tried:
so basically i receive the base64 image data from the front end, using axios POST request. then handle the image data in my django rest framework api View.
I have tried two variations:
1) writing the decoded base64 to a TemporaryFile, then passing it to the imageField.
2) opening the TemporaryFile using PIL.Image.open(img_temp) and then converting the PIL.Image to a InMemoryUploadedFile and passing that to the imageField.
However in both cases i get an error: image
:
["Upload a valid image. The file you uploaded was either not an image or a corrupted image."]
I'm not quite sure why i get this error because when i used the img.show(), the image came out fine.
Django rest framework
base64_data = request.data['image_data'][22:]
decode_image = base64.b64decode(base64_data)
img_temp = TemporaryFile()
img_temp.write(decode_image)
img_temp.flush()
img = PIL.Image.open(img_temp)
img_format = '.' + img.format
img.show()
image_io = BytesIO()
img.save(image_io, format=img.format)
file = InMemoryUploadedFile (
image_io,
None,
'photo' + img_format,
'image/' + img.format,
sys.getsizeof(image_io),
None,
)
img.close()
data = {
'image': File(img_temp) # I have tried passing File(img_tem) and "file" into the image field
}
serializer = ListSerializer(data=data, context={'request': request})
if serializer.is_valid():
instance = serializer.save()
instance.save()
UPDATE: figured it out
base64_data = request.data['image_data'][22:]
decode_image = base64.b64decode(base64_data)
img = PIL.Image.open(BytesIO(decode_image))
img_format = '.' + img.format
img.show()
fileData = BytesIO(decode_image)
file = InMemoryUploadedFile ( # arguments: 'file', 'field_name', 'name', 'content_type', 'size', and 'charset'
fileData,
None,
'photo' + img_format,
'image',
len(decode_image),
None,
)
img.close()
data = {
'image': file
}
serializer = ListSerializer(data=data, context={'request': request})
if serializer.is_valid():
instance = serializer.save()
instance.save()

PIL to Django ImageField

I try to create an image from an url and save it in my django model. If the first part works fine, I do not know how to associate the generated file to my object.
This is my function to generate the image file:
def get_remote_image(image_url, merchant_product_path):
im = None
name = ''
r = requests.get(image_url, stream=True)
if r.status_code == 200:
name = urlparse(image_url).path.split('/')[-1]
full_path = os.path.join(settings.MEDIA_ROOT, merchant_product_path)
if not os.path.exists(full_path):
os.makedirs(full_path)
im = Image.open(r.raw)
if im.mode != "RGB":
im = im.convert("RGB")
im.thumbnail((500, 500), Image.ANTIALIAS)
im.save(full_path + name, 'JPEG')
return {'im': im, 'name': name}
And now, the part to associate this file to my object:
i = get_remote_image(row['pict'], m.get_products_media_path())
obj, created = ProductLine.objects.update_or_create(
...
...
...
)
if i['im'] is not None:
try:
obj.main_picture.save(
i['name'],
ContentFile(i['im']),
save=True)
except TypeError:
continue
This code works but unfortunately, mu pictures are created in the correct folder, objects are created/update but each one has no picture file :(
Can someone tell me what's wrong ?
I've finally found a solution:
def get_remote_image(image_url):
im = None
name = ''
r = requests.get(image_url, stream=True)
if r.status_code == 200:
name = urlparse(image_url).path.split('/')[-1]
i = Image.open(r.raw)
buffer = BytesIO()
if i.mode != "RGB":
i = i.convert("RGB")
i.thumbnail((500, 500), Image.ANTIALIAS)
i.save(buffer, format='JPEG')
im = InMemoryUploadedFile(
buffer,
None,
name,
'image/jpeg',
buffer.tell(),
None)
return {'im': im, 'name': name}
and then:
obj, created = ProductLine.objects.update_or_create(
...
...
...
)
i = get_remote_image(row['pict'])
obj.main_picture.save(
os.path.join(m.get_products_image_path(), i['name']),
i['im'],
save=True)
Hope this will help some other users in this situation.
With a model like :
class ProductLine(models.Model):
name = models.CharField(max_length=250, null=True)
image = models.ImageField(null=True)
You can directly link the picture on your computer using is path instead of his binary content.
obj, created = ProductLine.objects.update_or_create(...)
obj.image.name = "/path/to/the/file"
obj.save()

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

issue while creating thumbnail in django

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)

Categories