1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2014 MediaGoblin contributors. See AUTHORS.
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU Affero General Public License for more details.
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 from __future__ import unicode_literals
24 from mediagoblin import mg_globals as mgg
25 from mediagoblin.processing import (BadMediaFail, store_public)
29 'NEAREST': Image.NEAREST,
30 'BILINEAR': Image.BILINEAR,
31 'BICUBIC': Image.BICUBIC,
32 'ANTIALIAS': Image.ANTIALIAS}
33 # TODO: want to say this instead:
34 #from mediagoblin.media_types.image import PIL_FILTERS
36 __VERSION__ = '0.1.3+' # releases get numbers, post release a "+" appended
37 _log = logging.getLogger(__name__)
40 _log.info('Hidden Original plugin set up!')
42 def stash_original(processor, quality=None, filter=None):
43 """This function creates a secret filename for storing the original
44 media file and saves that path with the key "hidden_original",
45 then downsizes the file (processor.process_filename) that
46 eventually gets stored as "original".
48 The `processor' argument is one of the CommonImageProcessors of
51 Note that since we downsize to the medium size, a separate
52 'medium' entry will not be created in the regular image process
53 function ('medium' versions are only created if the original is
54 larger than the medium size).
57 if u"hidden_original" in processor.entry.media_files \
58 and mgg.public_store.file_exists(
59 processor.entry.media_files[u"hidden_original"]):
60 # This should happen if we're called from Resizer instead of
64 # Stash away the actual original under the key "hidden_original".
65 secret_filename = "%s-%s" % (uuid.uuid4(),
66 processor.name_builder.fill('{basename}{ext}'))
67 # uuid4() as in get_unique_filepath, good enough for our purposes.
68 store_public(processor.entry,
70 processor.process_filename,
73 # Downsize the faux original to the "medium" size:
74 new_size = (mgg.global_config['media:' + 'medium']['max_width'],
75 mgg.global_config['media:' + 'medium']['max_height'])
77 # TODO: The following overlaps a bit with generate_thumb,
78 # resize_image and resize_tool, but those functions do way too
79 # much; e.g. storing metadata and the file itself.
81 quality = processor.image_config['quality']
83 filter = processor.image_config['resize_filter']
85 im = Image.open(processor.process_filename)
88 if im.size[0] > new_size[0] or im.size[1] > new_size[1]:
90 resize_filter = PIL_FILTERS[filter.upper()]
92 raise Exception('Filter "{0}" not found, choose one of {1}'.format(
94 u', '.join(PIL_FILTERS.keys())))
96 im.thumbnail(new_size, resize_filter)
98 # Overwrite the process_filename file with our downsized version:
99 with file(processor.process_filename, 'w') as resized_original:
100 im.save(resized_original, quality=quality)
101 # This will later get used as the "original" in copy_original
104 # A small file, just keep the original as is.
108 'setup': setup_plugin,
109 'imageprocessor_preprocess': stash_original