diff options
Diffstat (limited to 'synapse/media')
-rw-r--r-- | synapse/media/v0/content_repository.py | 2 | ||||
-rw-r--r-- | synapse/media/v1/__init__.py | 45 | ||||
-rw-r--r-- | synapse/media/v1/base_resource.py | 15 | ||||
-rw-r--r-- | synapse/media/v1/download_resource.py | 14 | ||||
-rw-r--r-- | synapse/media/v1/filepath.py | 2 | ||||
-rw-r--r-- | synapse/media/v1/media_repository.py | 2 | ||||
-rw-r--r-- | synapse/media/v1/thumbnail_resource.py | 27 | ||||
-rw-r--r-- | synapse/media/v1/thumbnailer.py | 10 | ||||
-rw-r--r-- | synapse/media/v1/upload_resource.py | 2 |
9 files changed, 95 insertions, 24 deletions
diff --git a/synapse/media/v0/content_repository.py b/synapse/media/v0/content_repository.py index ce5d3d153e..79ae0e3d74 100644 --- a/synapse/media/v0/content_repository.py +++ b/synapse/media/v0/content_repository.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2014 OpenMarket Ltd +# Copyright 2014, 2015 OpenMarket Ltd # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/synapse/media/v1/__init__.py b/synapse/media/v1/__init__.py index e69de29bb2..d6c6690577 100644 --- a/synapse/media/v1/__init__.py +++ b/synapse/media/v1/__init__.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2014, 2015 OpenMarket Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import PIL.Image + +# check for JPEG support. +try: + PIL.Image._getdecoder("rgb", "jpeg", None) +except IOError as e: + if str(e).startswith("decoder jpeg not available"): + raise Exception( + "FATAL: jpeg codec not supported. Install pillow correctly! " + " 'sudo apt-get install libjpeg-dev' then 'pip uninstall pillow &&" + " pip install pillow --user'" + ) +except Exception: + # any other exception is fine + pass + + +# check for PNG support. +try: + PIL.Image._getdecoder("rgb", "zip", None) +except IOError as e: + if str(e).startswith("decoder zip not available"): + raise Exception( + "FATAL: zip codec not supported. Install pillow correctly! " + " 'sudo apt-get install libjpeg-dev' then 'pip uninstall pillow &&" + " pip install pillow --user'" + ) +except Exception: + # any other exception is fine + pass diff --git a/synapse/media/v1/base_resource.py b/synapse/media/v1/base_resource.py index 2f5440ab64..688e7376ad 100644 --- a/synapse/media/v1/base_resource.py +++ b/synapse/media/v1/base_resource.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2014 OpenMarket Ltd +# Copyright 2014, 2015 OpenMarket Ltd # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -139,6 +139,7 @@ class BaseMediaResource(Resource): @download.addBoth def callback(media_info): del self.downloads[key] + return media_info return download @defer.inlineCallbacks @@ -201,7 +202,8 @@ class BaseMediaResource(Resource): defer.returnValue(media_info) @defer.inlineCallbacks - def _respond_with_file(self, request, media_type, file_path): + def _respond_with_file(self, request, media_type, file_path, + file_size=None): logger.debug("Responding with %r", file_path) if os.path.isfile(file_path): @@ -215,13 +217,20 @@ class BaseMediaResource(Resource): request.setHeader( b"Cache-Control", b"public,max-age=86400,s-maxage=86400" ) + if file_size is None: + stat = os.stat(file_path) + file_size = stat.st_size + + request.setHeader( + b"Content-Length", b"%d" % (file_size,) + ) with open(file_path, "rb") as f: yield FileSender().beginFileTransfer(f, request) request.finish() else: - self._respond_404() + self._respond_404(request) def _get_thumbnail_requirements(self, media_type): if media_type == "image/jpeg": diff --git a/synapse/media/v1/download_resource.py b/synapse/media/v1/download_resource.py index f3a6804e05..c585bb11f7 100644 --- a/synapse/media/v1/download_resource.py +++ b/synapse/media/v1/download_resource.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2014 OpenMarket Ltd +# Copyright 2014, 2015 OpenMarket Ltd # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -46,23 +46,29 @@ class DownloadResource(BaseMediaResource): def _respond_local_file(self, request, media_id): media_info = yield self.store.get_local_media(media_id) if not media_info: - self._respond_404() + self._respond_404(request) return media_type = media_info["media_type"] + media_length = media_info["media_length"] file_path = self.filepaths.local_media_filepath(media_id) - yield self._respond_with_file(request, media_type, file_path) + yield self._respond_with_file( + request, media_type, file_path, media_length + ) @defer.inlineCallbacks def _respond_remote_file(self, request, server_name, media_id): media_info = yield self._get_remote_media(server_name, media_id) media_type = media_info["media_type"] + media_length = media_info["media_length"] filesystem_id = media_info["filesystem_id"] file_path = self.filepaths.remote_media_filepath( server_name, filesystem_id ) - yield self._respond_with_file(request, media_type, file_path) + yield self._respond_with_file( + request, media_type, file_path, media_length + ) diff --git a/synapse/media/v1/filepath.py b/synapse/media/v1/filepath.py index 0078bc3d40..ed9a58e9d9 100644 --- a/synapse/media/v1/filepath.py +++ b/synapse/media/v1/filepath.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2014 OpenMarket Ltd +# Copyright 2014, 2015 OpenMarket Ltd # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/synapse/media/v1/media_repository.py b/synapse/media/v1/media_repository.py index 2070ec3c7f..461cc001f1 100644 --- a/synapse/media/v1/media_repository.py +++ b/synapse/media/v1/media_repository.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2014 OpenMarket Ltd +# Copyright 2014, 2015 OpenMarket Ltd # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/synapse/media/v1/thumbnail_resource.py b/synapse/media/v1/thumbnail_resource.py index e19620d456..84f5e3463c 100644 --- a/synapse/media/v1/thumbnail_resource.py +++ b/synapse/media/v1/thumbnail_resource.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2014 OpenMarket Ltd +# Copyright 2014, 2015 OpenMarket Ltd # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -100,11 +100,12 @@ class ThumbnailResource(BaseMediaResource): t_type = thumbnail_info["thumbnail_type"] t_method = thumbnail_info["thumbnail_method"] file_id = thumbnail_info["filesystem_id"] + t_length = thumbnail_info["thumbnail_length"] file_path = self.filepaths.remote_media_thumbnail( server_name, file_id, t_width, t_height, t_type, t_method, ) - yield self._respond_with_file(request, t_type, file_path) + yield self._respond_with_file(request, t_type, file_path, t_length) else: yield self._respond_default_thumbnail( request, media_info, width, height, method, m_type, @@ -139,11 +140,12 @@ class ThumbnailResource(BaseMediaResource): t_height = thumbnail_info["thumbnail_height"] t_type = thumbnail_info["thumbnail_type"] t_method = thumbnail_info["thumbnail_method"] + t_length = thumbnail_info["thumbnail_length"] file_path = self.filepaths.default_thumbnail( top_level_type, sub_type, t_width, t_height, t_type, t_method, ) - yield self.respond_with_file(request, t_type, file_path) + yield self.respond_with_file(request, t_type, file_path, t_length) def _select_thumbnail(self, desired_width, desired_height, desired_method, desired_type, thumbnail_infos): @@ -165,18 +167,27 @@ class ThumbnailResource(BaseMediaResource): aspect_quality, size_quality, type_quality, length_quality, info )) - return min(info_list)[-1] + if info_list: + return min(info_list)[-1] else: info_list = [] + info_list2 = [] for info in thumbnail_infos: t_w = info["thumbnail_width"] t_h = info["thumbnail_height"] t_method = info["thumbnail_method"] + size_quality = abs((d_w - t_w) * (d_h - t_h)) + type_quality = desired_type != info["thumbnail_type"] + length_quality = info["thumbnail_length"] if t_method == "scale" and (t_w >= d_w or t_h >= d_h): - size_quality = abs((d_w - t_w) * (d_h - t_h)) - type_quality = desired_type != info["thumbnail_type"] - length_quality = info["thumbnail_length"] info_list.append(( size_quality, type_quality, length_quality, info )) - return min(info_list)[-1] + elif t_method == "scale": + info_list2.append(( + size_quality, type_quality, length_quality, info + )) + if info_list: + return min(info_list)[-1] + else: + return min(info_list2)[-1] diff --git a/synapse/media/v1/thumbnailer.py b/synapse/media/v1/thumbnailer.py index 774ae4538f..28404f2b7b 100644 --- a/synapse/media/v1/thumbnailer.py +++ b/synapse/media/v1/thumbnailer.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2014 OpenMarket Ltd +# Copyright 2014, 2015 OpenMarket Ltd # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -48,7 +48,7 @@ class Thumbnailer(object): def scale(self, output_path, width, height, output_type): """Rescales the image to the given dimensions""" - scaled = self.image.resize((width, height), Image.BILINEAR) + scaled = self.image.resize((width, height), Image.ANTIALIAS) return self.save_image(scaled, output_type, output_path) def crop(self, output_path, width, height, output_type): @@ -65,7 +65,7 @@ class Thumbnailer(object): if width * self.height > height * self.width: scaled_height = (width * self.height) // self.width scaled_image = self.image.resize( - (width, scaled_height), Image.BILINEAR + (width, scaled_height), Image.ANTIALIAS ) crop_top = (scaled_height - height) // 2 crop_bottom = height + crop_top @@ -73,7 +73,7 @@ class Thumbnailer(object): else: scaled_width = (height * self.width) // self.height scaled_image = self.image.resize( - (scaled_width, height), Image.BILINEAR + (scaled_width, height), Image.ANTIALIAS ) crop_left = (scaled_width - width) // 2 crop_right = width + crop_left @@ -82,7 +82,7 @@ class Thumbnailer(object): def save_image(self, output_image, output_type, output_path): output_bytes_io = BytesIO() - output_image.save(output_bytes_io, self.FORMATS[output_type]) + output_image.save(output_bytes_io, self.FORMATS[output_type], quality=70) output_bytes = output_bytes_io.getvalue() with open(output_path, "wb") as output_file: output_file.write(output_bytes) diff --git a/synapse/media/v1/upload_resource.py b/synapse/media/v1/upload_resource.py index 5645b0df46..b1718a630b 100644 --- a/synapse/media/v1/upload_resource.py +++ b/synapse/media/v1/upload_resource.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2014 OpenMarket Ltd +# Copyright 2014, 2015 OpenMarket Ltd # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. |