|
@@ -1,13 +1,15 @@
|
|
|
+import cv2
|
|
|
+import os
|
|
|
import re
|
|
|
-from os import path, getcwd
|
|
|
|
|
|
-import cv2
|
|
|
from PIL import Image
|
|
|
from eventlet import tpool
|
|
|
-from flask import abort, send_from_directory
|
|
|
+from flask import abort
|
|
|
+from flask import send_from_directory
|
|
|
from flask.views import View
|
|
|
|
|
|
-from pycs.database.Database import Database
|
|
|
+from pycs.database.File import File
|
|
|
+from pycs.database.Project import Project
|
|
|
|
|
|
|
|
|
class GetResizedFile(View):
|
|
@@ -17,17 +19,13 @@ class GetResizedFile(View):
|
|
|
# pylint: disable=arguments-differ
|
|
|
methods = ['GET']
|
|
|
|
|
|
- def __init__(self, db: Database):
|
|
|
- # pylint: disable=invalid-name
|
|
|
- self.db = db
|
|
|
-
|
|
|
def dispatch_request(self, file_id: int, resolution: str):
|
|
|
# get file from database
|
|
|
- file = self.db.file(file_id)
|
|
|
+ file = File.query.get(file_id)
|
|
|
if file is None:
|
|
|
return abort(404, "file object not found")
|
|
|
|
|
|
- if not path.exists(file.path):
|
|
|
+ if not os.path.exists(file.path):
|
|
|
return abort(404, "image not found!")
|
|
|
|
|
|
project = file.project
|
|
@@ -38,103 +36,103 @@ class GetResizedFile(View):
|
|
|
max_height = int(resolution[1]) if len(resolution) > 1 else 2 ** 24
|
|
|
|
|
|
# send data
|
|
|
- file_directory, file_name = tpool.execute(self.resize_file,
|
|
|
- project, file, max_width, max_height)
|
|
|
+ file_directory, file_name = tpool.execute(resize_file,
|
|
|
+ project.id, file.id, max_width, max_height)
|
|
|
return send_from_directory(file_directory, file_name)
|
|
|
|
|
|
- @staticmethod
|
|
|
- def resize_file(project, file, max_width, max_height):
|
|
|
- """
|
|
|
- If file type equals video this function extracts a thumbnail first. It calls resize_image
|
|
|
- to resize and returns the resized files directory and name.
|
|
|
-
|
|
|
- :param project: associated project
|
|
|
- :param file: file object
|
|
|
- :param max_width: maximum image or thumbnail width
|
|
|
- :param max_height: maximum image or thumbnail height
|
|
|
- :return: resized file directory, resized file name
|
|
|
- """
|
|
|
- # get absolute path
|
|
|
- if path.isabs(file.path):
|
|
|
- abs_file_path = file.path
|
|
|
- else:
|
|
|
- abs_file_path = path.join(getcwd(), file.path)
|
|
|
-
|
|
|
- # extract video thumbnail
|
|
|
- if file.type == 'video':
|
|
|
- abs_target_path = path.join(getcwd(), project.root_folder, 'temp', f'{file.uuid}.jpg')
|
|
|
- GetResizedFile.create_thumbnail(abs_file_path, abs_target_path)
|
|
|
-
|
|
|
- abs_file_path = abs_target_path
|
|
|
-
|
|
|
- # resize image file
|
|
|
- abs_target_path = path.join(getcwd(), project.root_folder,
|
|
|
- 'temp', f'{file.uuid}_{max_width}_{max_height}.jpg')
|
|
|
- result = GetResizedFile.resize_image(abs_file_path, abs_target_path, max_width, max_height)
|
|
|
-
|
|
|
- # return path
|
|
|
- if result is not None:
|
|
|
- return path.split(abs_target_path)
|
|
|
-
|
|
|
- return path.split(abs_file_path)
|
|
|
-
|
|
|
- @staticmethod
|
|
|
- def resize_image(file_path, target_path, max_width, max_height):
|
|
|
- """
|
|
|
- resize an image so width < max_width and height < max_height
|
|
|
-
|
|
|
- :param file_path: path to source file
|
|
|
- :param target_path: path to target file
|
|
|
- :param max_width: maximum image width
|
|
|
- :param max_height: maximum image height
|
|
|
- :return:
|
|
|
- """
|
|
|
- # return if file exists
|
|
|
- if path.exists(target_path):
|
|
|
- return True
|
|
|
-
|
|
|
- # load full size image
|
|
|
- image = Image.open(file_path)
|
|
|
- img_width, img_height = image.size
|
|
|
-
|
|
|
- # abort if file is smaller than desired
|
|
|
- if img_width < max_width and img_height < max_height:
|
|
|
- return None
|
|
|
-
|
|
|
- # calculate target size
|
|
|
- target_width = int(max_width)
|
|
|
- target_height = int(max_width * img_height / img_width)
|
|
|
-
|
|
|
- if target_height > max_height:
|
|
|
- target_height = int(max_height)
|
|
|
- target_width = int(max_height * img_width / img_height)
|
|
|
-
|
|
|
- # resize image
|
|
|
- resized_image = image.resize((target_width, target_height))
|
|
|
-
|
|
|
- # save to file
|
|
|
- resized_image.save(target_path, quality=80)
|
|
|
+def resize_file(project_id, file_id, max_width, max_height):
|
|
|
+ """
|
|
|
+ If file type equals video this function extracts a thumbnail first. It calls resize_image
|
|
|
+ to resize and returns the resized files directory and name.
|
|
|
+
|
|
|
+ :param project: associated project
|
|
|
+ :param file: file object
|
|
|
+ :param max_width: maximum image or thumbnail width
|
|
|
+ :param max_height: maximum image or thumbnail height
|
|
|
+ :return: resized file directory, resized file name
|
|
|
+ """
|
|
|
+ file = File.query.get(file_id)
|
|
|
+ project = Project.query.get(project_id)
|
|
|
+
|
|
|
+ # get absolute path
|
|
|
+ if os.path.isabs(file.path):
|
|
|
+ abs_file_path = file.path
|
|
|
+ else:
|
|
|
+ abs_file_path = os.path.join(getcwd(), file.path)
|
|
|
+
|
|
|
+ # extract video thumbnail
|
|
|
+ if file.type == 'video':
|
|
|
+ abs_target_path = os.path.join(os.getcwd(), project.root_folder, 'temp', f'{file.uuid}.jpg')
|
|
|
+ create_thumbnail(abs_file_path, abs_target_path)
|
|
|
+
|
|
|
+ abs_file_path = abs_target_path
|
|
|
+
|
|
|
+ # resize image file
|
|
|
+ abs_target_path = os.path.join(os.getcwd(), project.root_folder,
|
|
|
+ 'temp', f'{file.uuid}_{max_width}_{max_height}.jpg')
|
|
|
+ result = resize_image(abs_file_path, abs_target_path, max_width, max_height)
|
|
|
+
|
|
|
+ # return path
|
|
|
+ if result is not None:
|
|
|
+ return os.path.split(abs_target_path)
|
|
|
+
|
|
|
+ return os.path.split(abs_file_path)
|
|
|
+
|
|
|
+def resize_image(file_path, target_path, max_width, max_height):
|
|
|
+ """
|
|
|
+ resize an image so width < max_width and height < max_height
|
|
|
+
|
|
|
+ :param file_path: path to source file
|
|
|
+ :param target_path: path to target file
|
|
|
+ :param max_width: maximum image width
|
|
|
+ :param max_height: maximum image height
|
|
|
+ :return:
|
|
|
+ """
|
|
|
+ # return if file exists
|
|
|
+ if os.path.exists(target_path):
|
|
|
return True
|
|
|
|
|
|
- @staticmethod
|
|
|
- def create_thumbnail(file_path, target_path):
|
|
|
- """
|
|
|
- extract a thumbnail from a video
|
|
|
+ # load full size image
|
|
|
+ image = Image.open(file_path)
|
|
|
+ img_width, img_height = image.size
|
|
|
+
|
|
|
+ # abort if file is smaller than desired
|
|
|
+ if img_width < max_width and img_height < max_height:
|
|
|
+ return None
|
|
|
+
|
|
|
+ # calculate target size
|
|
|
+ target_width = int(max_width)
|
|
|
+ target_height = int(max_width * img_height / img_width)
|
|
|
+
|
|
|
+ if target_height > max_height:
|
|
|
+ target_height = int(max_height)
|
|
|
+ target_width = int(max_height * img_width / img_height)
|
|
|
|
|
|
- :param file_path: path to source file
|
|
|
- :param target_path: path to target file
|
|
|
- :return:
|
|
|
- """
|
|
|
- # return if file exists
|
|
|
- if path.exists(target_path):
|
|
|
- return
|
|
|
+ # resize image
|
|
|
+ resized_image = image.resize((target_width, target_height))
|
|
|
+
|
|
|
+ # save to file
|
|
|
+ resized_image.save(target_path, quality=80)
|
|
|
+ return True
|
|
|
+
|
|
|
+def create_thumbnail(file_path, target_path):
|
|
|
+ """
|
|
|
+ extract a thumbnail from a video
|
|
|
+
|
|
|
+ :param file_path: path to source file
|
|
|
+ :param target_path: path to target file
|
|
|
+ :return:
|
|
|
+ """
|
|
|
+ # return if file exists
|
|
|
+ if os.path.exists(target_path):
|
|
|
+ return
|
|
|
|
|
|
- # load video
|
|
|
- video = cv2.VideoCapture(file_path)
|
|
|
+ # load video
|
|
|
+ video = cv2.VideoCapture(file_path)
|
|
|
|
|
|
- # create thumbnail
|
|
|
- _, image = video.read()
|
|
|
- cv2.imwrite(target_path, image)
|
|
|
+ # create thumbnail
|
|
|
+ _, image = video.read()
|
|
|
+ cv2.imwrite(target_path, image)
|
|
|
|
|
|
- # close video file
|
|
|
- video.release()
|
|
|
+ # close video file
|
|
|
+ video.release()
|