Merge remote-tracking branch 'refs/remotes/rodney757/reprocessing'
authorChristopher Allan Webber <cwebber@dustycloud.org>
Wed, 18 Sep 2013 19:45:23 +0000 (14:45 -0500)
committerChristopher Allan Webber <cwebber@dustycloud.org>
Wed, 18 Sep 2013 19:45:23 +0000 (14:45 -0500)
Conflicts:
mediagoblin/db/migrations.py

mediagoblin/db/migrations.py
mediagoblin/db/models.py
mediagoblin/media_types/ascii/processing.py
mediagoblin/media_types/image/processing.py

index e2a0bf260647bf5b594e4e366e899f470d99bb13..a88518f45c8b38d918c2d6f5df75cc5cd32e5e32 100644 (file)
@@ -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()
index a26756786a67ecc9768edd26b79fc5b12656d066..809e47220dd6b6901b2361b8d563ca045ec7caac 100644 (file)
@@ -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'),
index 3b287877d3047de13fa19c437b028edfc05fbec2..ef4727de243d242e64fca703d8d80d44cb62f584 100644 (file)
@@ -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):
     """
index 4c7bdb15935d625ec4ddbf246742ec7315031be9..a0ad2ce81d36e0781d9885f2940d825b332adf79 100644 (file)
@@ -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']