diff options
author | Rodney Ewing <ewing.rj@gmail.com> | 2013-08-02 11:40:41 -0700 |
---|---|---|
committer | Rodney Ewing <ewing.rj@gmail.com> | 2013-08-16 15:30:14 -0700 |
commit | 9a2c66ca9ef763fa68dc09a483c02fe2ee02d78f (patch) | |
tree | fde0cac99182ba200d2274978dd425d6e4eb33b7 | |
parent | 273c79513d82b03b99035dcfa47e839c61322483 (diff) | |
download | mediagoblin-9a2c66ca9ef763fa68dc09a483c02fe2ee02d78f.tar.lz mediagoblin-9a2c66ca9ef763fa68dc09a483c02fe2ee02d78f.tar.xz mediagoblin-9a2c66ca9ef763fa68dc09a483c02fe2ee02d78f.zip |
added image reprocessing
-rw-r--r-- | mediagoblin/gmg_commands/reprocess.py | 3 | ||||
-rw-r--r-- | mediagoblin/media_types/image/__init__.py | 47 | ||||
-rw-r--r-- | mediagoblin/media_types/image/processing.py | 94 | ||||
-rw-r--r-- | mediagoblin/processing/__init__.py | 17 | ||||
-rw-r--r-- | mediagoblin/processing/task.py | 6 | ||||
-rw-r--r-- | mediagoblin/submit/lib.py | 8 |
6 files changed, 134 insertions, 41 deletions
diff --git a/mediagoblin/gmg_commands/reprocess.py b/mediagoblin/gmg_commands/reprocess.py index 0390c48d..f6b9e653 100644 --- a/mediagoblin/gmg_commands/reprocess.py +++ b/mediagoblin/gmg_commands/reprocess.py @@ -13,6 +13,7 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +from mediagoblin import mg_globals from mediagoblin.db.models import MediaEntry from mediagoblin.gmg_commands import util as commands_util from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ @@ -143,6 +144,8 @@ def reprocess(args): _set_media_state(args) _set_media_type(args) + import ipdb + ipdb.set_trace() if not args[0].media_id: return _reprocess_all(args) diff --git a/mediagoblin/media_types/image/__init__.py b/mediagoblin/media_types/image/__init__.py index a1b43479..3a056718 100644 --- a/mediagoblin/media_types/image/__init__.py +++ b/mediagoblin/media_types/image/__init__.py @@ -15,13 +15,18 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import argparse import datetime +import logging +from mediagoblin.db.models import MediaEntry from mediagoblin.media_types import MediaManagerBase from mediagoblin.media_types.image.processing import process_image, \ sniff_handler +from mediagoblin.submit.lib import run_process_media from mediagoblin.tools import pluginapi from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ +_log = logging.getLogger(__name__) + ACCEPTED_EXTENSIONS = ["jpg", "jpeg", "png", "gif", "tiff"] MEDIA_TYPE = 'mediagoblin.media_types.image' @@ -69,7 +74,7 @@ def get_media_type_and_manager(ext): def reprocess_action(args): if args[0].state == 'processed': print _('\n Available reprocessing actions for processed images:' - '\n \t --resize: thumbnail or medium' + '\n \t --resize: thumb or medium' '\n Options:' '\n \t --size: max_width max_height (defaults to config specs)') return True @@ -78,8 +83,7 @@ def reprocess_action(args): def _parser(args): parser = argparse.ArgumentParser() parser.add_argument( - '--resize', - action='store_true') + '--resize') parser.add_argument( '--size', nargs=2) @@ -100,6 +104,9 @@ def _check_eligible(entry_args, reprocess_args): if reprocess_args.resize: raise Exception(_('You can not run --resize on media that has not' 'been processed.')) + if reprocess_args.size: + _log.warn('With --initial_processing, the --size flag will be' + ' ignored.') if entry_args.state == 'processing': raise Exception(_('We currently do not support reprocessing on media' @@ -111,8 +118,38 @@ def media_reprocess(args): entry_args = args[0] _check_eligible(entry_args, reprocess_args) - import ipdb - ipdb.set_trace() + if reprocess_args.initial_processing: + for id in entry_args.media_id: + entry = MediaEntry.query.filter_by(id=id).first() + # Should we get the feed_url? + run_process_media(entry) + + elif reprocess_args.resize: + if reprocess_args.resize == 'medium' or reprocess_args.resize == \ + 'thumb': + for id in entry_args.media_id: + entry = MediaEntry.query.filter_by(id=id).first() + + # For now we can only reprocess with the original file + if not entry.media_files.get('original'): + raise Exception(_('The original file for this media entry' + 'does not exist.')) + + reprocess_info = {'resize': reprocess_args.resize} + + if reprocess_args.size and len(reprocess_args.size) == 2: + reprocess_info['max_width'] = reprocess_args.size[0] + reprocess_info['max_height'] = reprocess_args.size[1] + + run_process_media(entry, reprocess_info) + + else: + raise Exception(_('The --resize flag must set either "thumb"' + ' or "medium".')) + + else: + _log.warn('You must set either --resize or --initial_processing flag' + ' to reprocess an image.') hooks = { diff --git a/mediagoblin/media_types/image/processing.py b/mediagoblin/media_types/image/processing.py index baf2ac7e..4f619f47 100644 --- a/mediagoblin/media_types/image/processing.py +++ b/mediagoblin/media_types/image/processing.py @@ -74,11 +74,13 @@ def resize_image(proc_state, resized, keyname, target_name, new_size, def resize_tool(proc_state, force, keyname, target_name, - conversions_subdir, exif_tags): + conversions_subdir, exif_tags, new_size=None): # filename -- the filename of the original image being resized filename = proc_state.get_queued_filename() - max_width = mgg.global_config['media:' + keyname]['max_width'] - max_height = mgg.global_config['media:' + keyname]['max_height'] + if not new_size: + max_width = mgg.global_config['media:' + keyname]['max_width'] + max_height = mgg.global_config['media:' + keyname]['max_height'] + new_size = (max_width, max_height) # If the size of the original file exceeds the specified size for the desized # file, a target_name file is created and later associated with the media # entry. @@ -93,7 +95,7 @@ def resize_tool(proc_state, force, keyname, target_name, or exif_image_needs_rotation(exif_tags): resize_image( proc_state, im, unicode(keyname), target_name, - (max_width, max_height), + new_size, exif_tags, conversions_subdir) @@ -119,7 +121,7 @@ def sniff_handler(media_file, **kw): return None -def process_image(proc_state): +def process_image(proc_state, reprocess_info=None): """Code to process an image. Will be run by celery. A Workbench() represents a local tempory dir. It is automatically @@ -127,45 +129,75 @@ def process_image(proc_state): """ entry = proc_state.entry workbench = proc_state.workbench - + import ipdb + ipdb.set_trace() # Conversions subdirectory to avoid collisions conversions_subdir = os.path.join( workbench.dir, 'conversions') os.mkdir(conversions_subdir) - queued_filename = proc_state.get_queued_filename() - name_builder = FilenameBuilder(queued_filename) + if reprocess_info: + _reprocess_image(proc_state, reprocess_info, conversions_subdir) + + else: + queued_filename = proc_state.get_queued_filename() + name_builder = FilenameBuilder(queued_filename) - # EXIF extraction - exif_tags = extract_exif(queued_filename) - gps_data = get_gps_data(exif_tags) + # EXIF extraction + exif_tags = extract_exif(queued_filename) + gps_data = get_gps_data(exif_tags) - # Always create a small thumbnail - resize_tool(proc_state, True, 'thumb', - name_builder.fill('{basename}.thumbnail{ext}'), - conversions_subdir, exif_tags) + # Always create a small thumbnail + resize_tool(proc_state, True, 'thumb', + name_builder.fill('{basename}.thumbnail{ext}'), + conversions_subdir, exif_tags) + + # Possibly create a medium + resize_tool(proc_state, False, 'medium', + name_builder.fill('{basename}.medium{ext}'), + conversions_subdir, exif_tags) + + # Copy our queued local workbench to its final destination + proc_state.copy_original(name_builder.fill('{basename}{ext}')) + + # Remove queued media file from storage and database + proc_state.delete_queue_file() - # Possibly create a medium - resize_tool(proc_state, False, 'medium', - name_builder.fill('{basename}.medium{ext}'), - conversions_subdir, exif_tags) + # Insert exif data into database + exif_all = clean_exif(exif_tags) - # Copy our queued local workbench to its final destination - proc_state.copy_original(name_builder.fill('{basename}{ext}')) + if len(exif_all): + entry.media_data_init(exif_all=exif_all) - # Remove queued media file from storage and database - proc_state.delete_queue_file() + if len(gps_data): + for key in list(gps_data.keys()): + gps_data['gps_' + key] = gps_data.pop(key) + entry.media_data_init(**gps_data) - # Insert exif data into database - exif_all = clean_exif(exif_tags) - if len(exif_all): - entry.media_data_init(exif_all=exif_all) +def _reprocess_image(proc_state, reprocess_info, conversions_subdir): + reprocess_filename = proc_state.get_reprocess_filename() + name_builder = FilenameBuilder(reprocess_filename) - if len(gps_data): - for key in list(gps_data.keys()): - gps_data['gps_' + key] = gps_data.pop(key) - entry.media_data_init(**gps_data) + exif_tags = extract_exif(reprocess_filename) + + if reprocess_info.get('max_width'): + max_width = reprocess_info['max_width'] + else: + max_width = mgg.global_config \ + ['media:' + reprocess_info['resize']]['max_width'] + + if reprocess_info.get('max_height'): + max_height = reprocess_info['max_height'] + else: + max_height = mgg.global_config \ + ['media:' + reprocess_info['resize']]['max_height'] + + new_size = (max_width, max_height) + + resize_tool(proc_state, False, reprocess_info['resize'], + name_builder.fill('{basename}.thumbnail{ext}'), + conversions_subdir, exif_tags, new_size) if __name__ == '__main__': diff --git a/mediagoblin/processing/__init__.py b/mediagoblin/processing/__init__.py index f3a85940..bbe9f364 100644 --- a/mediagoblin/processing/__init__.py +++ b/mediagoblin/processing/__init__.py @@ -87,6 +87,7 @@ class ProcessingState(object): self.entry = entry self.workbench = None self.queued_filename = None + self.reprocess_filename = None def set_workbench(self, wb): self.workbench = wb @@ -128,6 +129,22 @@ class ProcessingState(object): mgg.queue_store.delete_dir(queued_filepath[:-1]) # rm dir self.entry.queued_media_file = [] + def get_reprocess_filename(self): + """ + Get the filename to use during reprocessing + """ + # Currently only returns the original file, but eventually will return + # the highest quality file if the original doesn't exist + if self.reprocess_filename is not None: + return self.reprocess_filename + + reprocess_filepath = self.entry.media_files['original'][2] + reprocess_filename = self.workbench.local_file( + mgg.public_store, reprocess_filepath, + 'original') + self.reprocess_filename = reprocess_filename + return reprocess_filename + def mark_entry_failed(entry_id, exc): """ diff --git a/mediagoblin/processing/task.py b/mediagoblin/processing/task.py index 9af192ed..c0dfb9b4 100644 --- a/mediagoblin/processing/task.py +++ b/mediagoblin/processing/task.py @@ -68,13 +68,15 @@ class ProcessMedia(task.Task): """ Pass this entry off for processing. """ - def run(self, media_id, feed_url): + def run(self, media_id, feed_url, reprocess_info=None): """ Pass the media entry off to the appropriate processing function (for now just process_image...) :param feed_url: The feed URL that the PuSH server needs to be updated for. + :param reprocess: A dict containing all of the necessary reprocessing + info for the media_type. """ entry = MediaEntry.query.get(media_id) @@ -89,7 +91,7 @@ class ProcessMedia(task.Task): with mgg.workbench_manager.create() as workbench: proc_state.set_workbench(workbench) # run the processing code - entry.media_manager.processor(proc_state) + entry.media_manager.processor(proc_state, reprocess_info) # We set the state to processed and save the entry here so there's # no need to save at the end of the processing stage, probably ;) diff --git a/mediagoblin/submit/lib.py b/mediagoblin/submit/lib.py index 7e85696b..3619a329 100644 --- a/mediagoblin/submit/lib.py +++ b/mediagoblin/submit/lib.py @@ -76,17 +76,19 @@ def prepare_queue_task(app, entry, filename): return queue_file -def run_process_media(entry, feed_url=None): +def run_process_media(entry, feed_url=None, reprocess_info=None): """Process the media asynchronously :param entry: MediaEntry() instance to be processed. :param feed_url: A string indicating the feed_url that the PuSH servers should be notified of. This will be sth like: `request.urlgen( 'mediagoblin.user_pages.atom_feed',qualified=True, - user=request.user.username)`""" + user=request.user.username)` + :param reprocess: A dict containing all of the necessary reprocessing + info for the given media_type""" try: process_media.apply_async( - [entry.id, feed_url], {}, + [entry.id, feed_url, reprocess_info], {}, task_id=entry.queued_task_id) except BaseException as exc: # The purpose of this section is because when running in "lazy" |