From: Christopher Allan Webber Date: Wed, 18 Sep 2013 19:45:23 +0000 (-0500) Subject: Merge remote-tracking branch 'refs/remotes/rodney757/reprocessing' X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=529eb17b38ac08c956164e8b829ea556db1f32f4;hp=28eab59acef05b5f38052941483f900d2e78c50b;p=mediagoblin.git Merge remote-tracking branch 'refs/remotes/rodney757/reprocessing' Conflicts: mediagoblin/db/migrations.py --- diff --git a/mediagoblin/db/migrations.py b/mediagoblin/db/migrations.py index e2a0bf26..a88518f4 100644 --- a/mediagoblin/db/migrations.py +++ b/mediagoblin/db/migrations.py @@ -494,3 +494,15 @@ def upload_limits(db): col.create(media_entry_table) db.commit() + + +@RegisterMigration(17, MIGRATIONS) +def add_file_metadata(db): + """Add file_metadata to MediaFile""" + metadata = MetaData(bind=db.bind) + media_file_table = inspect_table(metadata, "core__mediafiles") + + col = Column('file_metadata', JSONEncoded) + col.create(media_file_table) + + db.commit() diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py index a2675678..809e4722 100644 --- a/mediagoblin/db/models.py +++ b/mediagoblin/db/models.py @@ -267,6 +267,34 @@ class MediaEntry(Base, MediaEntryMixin): if media is not None: return media.url_for_self(urlgen) + def get_file_metadata(self, file_key, metadata_key=None): + """ + Return the file_metadata dict of a MediaFile. If metadata_key is given, + return the value of the key. + """ + media_file = MediaFile.query.filter_by(media_entry=self.id, + name=unicode(file_key)).first() + + if media_file: + if metadata_key: + return media_file.file_metadata.get(metadata_key, None) + + return media_file.file_metadata + + def set_file_metadata(self, file_key, **kwargs): + """ + Update the file_metadata of a MediaFile. + """ + media_file = MediaFile.query.filter_by(media_entry=self.id, + name=unicode(file_key)).first() + + file_metadata = media_file.file_metadata or {} + + for key, value in kwargs.iteritems(): + file_metadata[key] = value + + media_file.file_metadata = file_metadata + @property def media_data(self): return getattr(self, self.media_data_ref) @@ -363,6 +391,7 @@ class MediaFile(Base): nullable=False) name_id = Column(SmallInteger, ForeignKey(FileKeynames.id), nullable=False) file_path = Column(PathTupleWithSlashes) + file_metadata = Column(JSONEncoded) __table_args__ = ( PrimaryKeyConstraint('media_entry', 'name_id'), diff --git a/mediagoblin/media_types/ascii/processing.py b/mediagoblin/media_types/ascii/processing.py index 3b287877..ef4727de 100644 --- a/mediagoblin/media_types/ascii/processing.py +++ b/mediagoblin/media_types/ascii/processing.py @@ -120,6 +120,9 @@ class CommonAsciiProcessor(MediaProcessor): thumb_size = (mgg.global_config['media:thumb']['max_width'], mgg.global_config['media:thumb']['max_height']) + if self._skip_resizing(font, thumb_size): + return + tmp_thumb = os.path.join( self.conversions_subdir, self.name_builder.fill('{basename}.thumbnail.png')) @@ -144,10 +147,33 @@ class CommonAsciiProcessor(MediaProcessor): Image.ANTIALIAS) thumb.save(thumb_file) + thumb_info = {'font': font, + 'width': thumb_size[0], + 'height': thumb_size[1]} + + self.entry.set_file_metadata('thumb', **thumb_info) + _log.debug('Copying local file to public storage') store_public(self.entry, 'thumb', tmp_thumb, self.name_builder.fill('{basename}.thumbnail.jpg')) + def _skip_resizing(self, font, thumb_size): + thumb_info = self.entry.get_file_metadata('thumb') + + if not thumb_info: + return False + + skip = True + + if thumb_info.get('font') != font: + skip = False + elif thumb_info.get('width') != thumb_size[0]: + skip = False + elif thumb_info.get('height') != thumb_size[1]: + skip = False + + return skip + class InitialProcessor(CommonAsciiProcessor): """ diff --git a/mediagoblin/media_types/image/processing.py b/mediagoblin/media_types/image/processing.py index 4c7bdb15..a0ad2ce8 100644 --- a/mediagoblin/media_types/image/processing.py +++ b/mediagoblin/media_types/image/processing.py @@ -76,6 +76,14 @@ def resize_image(entry, resized, keyname, target_name, new_size, resized.save(resized_file, quality=quality) store_public(entry, keyname, tmp_resized_filename, target_name) + # store the thumb/medium info + image_info = {'width': new_size[0], + 'height': new_size[1], + 'quality': quality, + 'filter': filter} + + entry.set_file_metadata(keyname, **image_info) + def resize_tool(entry, force, keyname, orig_file, target_name, @@ -86,6 +94,13 @@ def resize_tool(entry, max_height = mgg.global_config['media:' + keyname]['max_height'] new_size = (max_width, max_height) + # If thumb or medium is already the same quality and size, then don't + # reprocess + if _skip_resizing(entry, keyname, new_size, quality, filter): + _log.info('{0} of same size and quality already in use, skipping ' + 'resizing of media {1}.'.format(keyname, entry.id)) + return + # 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. @@ -105,6 +120,32 @@ def resize_tool(entry, quality, filter) +def _skip_resizing(entry, keyname, size, quality, filter): + """ + Determines wither the saved thumb or medium is of the same quality and size + """ + image_info = entry.get_file_metadata(keyname) + + if not image_info: + return False + + skip = True + + if image_info.get('width') != size[0]: + skip = False + + elif image_info.get('height') != size[1]: + skip = False + + elif image_info.get('filter') != filter: + skip = False + + elif image_info.get('quality') != quality: + skip = False + + return skip + + SUPPORTED_FILETYPES = ['png', 'gif', 'jpg', 'jpeg', 'tiff']