From 3415220565a123b0be7a0d3650a97c549238fdd2 Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Mon, 19 Feb 2018 12:36:53 -0500 Subject: [PATCH] Added resize images task --- requirements.txt | 4 +++- worker/tasks.py | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 14959fb4..cdf8b383 100644 --- a/requirements.txt +++ b/requirements.txt @@ -30,10 +30,12 @@ Markdown==2.6.7 olefile==0.44 openapi-codec==1.1.7 packaging==16.8 +piexif==1.0.13 pilkit==2.0 Pillow==4.3.0 pip-autoremove==0.9.0 -psycopg2==2.6.2 +psycopg2==2.7.4 +psycopg2-binary==2.7.4 PyJWT==1.5.3 pyparsing==2.1.10 pytz==2018.3 diff --git a/worker/tasks.py b/worker/tasks.py index c39b7ab3..a57aa7e3 100644 --- a/worker/tasks.py +++ b/worker/tasks.py @@ -1,5 +1,9 @@ +import os import traceback +import re + +import piexif from django.core.exceptions import ObjectDoesNotExist from django.db.models import Count from django.db.models import Q @@ -12,6 +16,9 @@ from nodeodm.models import ProcessingNode from .celery import app from celery.utils.log import get_task_logger from django.db import transaction +from PIL import Image +from functools import partial +from multiprocessing import Pool, cpu_count logger = get_task_logger(__name__) @@ -78,3 +85,56 @@ def process_pending_tasks(): for task in tasks: process_task.delay(task.id) + +@app.task +def resize_image(image_path, resize_to): + try: + exif_dict = piexif.load(image_path) + im = Image.open(image_path) + path, ext = os.path.splitext(image_path) + resized_image_path = os.path.join(path + '.resized' + ext) + + width, height = im.size + max_side = max(width, height) + if max_side < resize_to: + logger.warning('We are making {} bigger ({} --> {})'.format(image_path, max_side, resize_to)) + + ratio = float(resize_to) / float(max_side) + resized_width = int(width * ratio) + resized_height = int(height * ratio) + + im.thumbnail((resized_width, resized_height), Image.LANCZOS) + + if len(exif_dict['Exif']) > 0: + exif_dict['Exif'][piexif.ExifIFD.PixelXDimension] = resized_width + exif_dict['Exif'][piexif.ExifIFD.PixelYDimension] = resized_height + im.save(resized_image_path, "JPEG", exif=piexif.dump(exif_dict), quality=100) + else: + im.save(resized_image_path, "JPEG", quality=100) + + im.close() + + # Delete original image, rename resized image to original + os.remove(image_path) + os.rename(resized_image_path, image_path) + + logger.info("Resized {}".format(os.path.basename(resized_image_path))) + except IOError as e: + logger.warning("Cannot resize {}: {}.".format(image_path, str(e))) + return None + + return image_path + +@app.task +def resize_images(directory, resize_to): + """ + Destructively resize a directory of JPG images while retaining EXIF tags. + Resulting images are always converted to JPG. + TODO: add support for tiff files + :return list containing paths of resized images + """ + images_path = [os.path.join(directory, f) for f in os.listdir(directory) if re.match(r'.*\.jpe?g$', f, re.IGNORECASE)] + resized_images = list(filter(lambda i: i is not None, Pool(cpu_count()).map( + partial(resize_image, resize_to=resize_to), + images_path))) + return resized_images \ No newline at end of file