Skip to content

Commit

Permalink
Resize photo before saving
Browse files Browse the repository at this point in the history
  • Loading branch information
VirginiaDooley committed Apr 30, 2023
1 parent 7b54321 commit 89507fd
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 5 deletions.
14 changes: 10 additions & 4 deletions ynr/apps/moderation_queue/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@
from django.core.mail import send_mail
from django.template.loader import render_to_string
from django.urls import reverse
from moderation_queue.helpers import convert_image_to_png, rotate_photo
from moderation_queue.helpers import (
convert_image_to_png,
resize_photo,
rotate_photo,
)
from people.forms.forms import StrippedCharField
from PIL import Image as PILImage

Expand Down Expand Up @@ -55,11 +59,13 @@ def clean(self):

def save(self, commit):
"""
Before saving, rotate the image and convert the image to a PNG.
This is done while the image is still an InMemoryUpload object
Before saving, resize and rotate the image as needed
and convert the image to a PNG. This is done while the
image is still an InMemoryUpload object.
"""

photo = resize_photo(photo=self.instance.image)
photo = rotate_photo(image=self.instance.image)
# pass a PIL image to the convert_image_to_png function
png_image = convert_image_to_png(photo)
filename = self.instance.image.name
extension = filename.split(".")[-1]
Expand Down
14 changes: 13 additions & 1 deletion ynr/apps/moderation_queue/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,18 @@ def image_form_valid_response(request, person, image_form):
)


def resize_photo(photo):
if photo.size > 5000000:
image_path = photo.path
photo = PillowImage.open(photo)
# resize the photo to less than or equal to 5MB and return it
photo = photo.resize(
(photo.width // 2, photo.height // 2), PillowImage.ANTIALIAS
)
photo.save(image_path, optimize=True, quality=95)
return photo


def convert_image_to_png(photo):
# Some uploaded images are CYMK, which gives you an error when
# you try to write them as PNG, so convert to RGBA (this is
Expand All @@ -54,7 +66,7 @@ def convert_image_to_png(photo):
# If the photo is not already a PillowImage object
# coming from the form, then we need to
# open it as a PillowImage object before
# converting
# converting it to RGBA.
if not isinstance(photo, PillowImage.Image):
photo = PillowImage.open(photo)
converted = photo.convert("RGBA")
Expand Down
4 changes: 4 additions & 0 deletions ynr/apps/moderation_queue/tests/paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@
QUEUED_IMAGE_FILENAME = abspath(
join(dirname(__file__), "media/queued-images/example-queued-image.png")
)

XL_IMAGE_FILENAME = abspath(
join(dirname(__file__), "example-queued-image-xl.jpg")
)
25 changes: 25 additions & 0 deletions ynr/apps/moderation_queue/tests/test_upload_photo.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
from os.path import dirname, join, realpath
from shutil import rmtree
from urllib.parse import urlsplit
Expand All @@ -19,6 +20,7 @@
from moderation_queue.tests.paths import (
EXAMPLE_IMAGE_FILENAME,
ROTATED_IMAGE_FILENAME,
XL_IMAGE_FILENAME,
)
from people.tests.factories import PersonFactory
from PIL import Image as PillowImage
Expand All @@ -34,6 +36,7 @@ class PhotoUploadImageTests(UK2015ExamplesMixin, WebTest):

example_image_filename = EXAMPLE_IMAGE_FILENAME
rotated_image_filename = ROTATED_IMAGE_FILENAME
xl_image_filename = XL_IMAGE_FILENAME

@classmethod
def setUpClass(cls):
Expand Down Expand Up @@ -160,6 +163,28 @@ def test_shows_photo_policy_text_in_photo_upload_page(self):
response = self.app.get(upload_form_url, user=self.test_upload_user)
self.assertContains(response, "Photo policy")

def test_resize_image(self, *all_mock_requests):
# Test that the image is resized to a maximum of 5MB
# during the photo upload save process.
# This test uses a 6MB image.

# first, confirm the MB size of the test image before upload
image_size = os.path.getsize(self.xl_image_filename)
self.assertGreater(image_size, 5000000)

upload_form_url = reverse("photo-upload", kwargs={"person_id": "2009"})
form_page_response = self.app.get(
upload_form_url, user=self.test_upload_user
)
form = form_page_response.forms["person-upload-photo-image"]
with open(self.xl_image_filename, "rb") as image:
form["image"] = Upload("xl_image.jpg", image.read())
form["why_allowed"] = "profile-photo"
form["justification_for_use"] = "I took this photo"
upload_response = form.submit()
self.assertEqual(upload_response.status_code, 302)
self.assertLessEqual(image_size, 5000000)

def test_rotate_image_from_file_upload(self, *all_mock_requests):
exif = PillowImage.open(ROTATED_IMAGE_FILENAME)._getexif()
# assert exif[274] == 1 before upload
Expand Down

0 comments on commit 89507fd

Please sign in to comment.