]> git.ipfire.org Git - ipfire.org.git/commitdiff
Cache generated thumbnails
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 7 May 2019 16:27:54 +0000 (17:27 +0100)
committerMichael Tremer <michael.tremer@ipfire.org>
Tue, 7 May 2019 16:28:30 +0000 (17:28 +0100)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/backend/accounts.py
src/backend/util.py
src/backend/wiki.py

index e2352f5512d42de9a808632c91819181d6aa47ce..8f6659bcd64b9982c31e0ab0329198e69b915510 100644 (file)
@@ -767,30 +767,24 @@ class Account(Object):
                return url
 
        def get_avatar(self, size=None):
-               avatar = self._get_bytes("jpegPhoto")
-               if not avatar:
-                       return
-
-               if not size:
-                       return avatar
+               photo = self._get_bytes("jpegPhoto")
 
-               return self._resize_avatar(avatar, size)
+               # Return the raw image if no size was requested
+               if size is None:
+                       return photo
 
-       def _resize_avatar(self, image, size):
-               image = PIL.Image.open(io.BytesIO(image))
+               # Try to retrieve something from the cache
+               avatar = self.memcache.get("accounts:%s:avatar:%s" % (self.uid, size))
+               if avatar:
+                       return avatar
 
-               # Resize the image to the desired resolution (and make it square)
-               thumbnail = PIL.ImageOps.fit(image, (size, size), PIL.Image.ANTIALIAS)
+               # Generate a new thumbnail
+               avatar = util.generate_thumbnail(photo, size)
 
-               with io.BytesIO() as f:
-                       # If writing out the image does not work with optimization,
-                       # we try to write it out without any optimization.
-                       try:
-                               thumbnail.save(f, image.format, optimize=True, quality=98)
-                       except:
-                               thumbnail.save(f, image.format, quality=98)
+               # Save to cache for 15m
+               self.memcache.set("accounts:%s:avatar:%s" % (self.uid, size), avatar, 900)
 
-                       return f.getvalue()
+               return avatar
 
        def upload_avatar(self, avatar):
                self._set("jpegPhoto", avatar)
index 89e7f0f52401d9c68948ebbfc894a333b6fb6b89..aaa2b62c1e6a5964ffb832d16c284834dc03d03d 100644 (file)
@@ -1,5 +1,9 @@
 #!/usr/bin/python3
 
+import PIL.Image
+import PIL.ImageFilter
+import io
+import logging
 import random
 import re
 import string
@@ -70,3 +74,49 @@ def normalize(s):
        s = re.sub(r"[^\w]+", " ", s)
 
        return "-".join(s.split())
+
+def generate_thumbnail(data, size, **args):
+       assert data, "No image data received"
+
+       image = PIL.Image.open(io.BytesIO(data))
+
+       # Save image format
+       format = image.format
+
+       # Remove any alpha-channels
+       if image.format == "JPEG" and not image.mode == "RGB":
+               # Make a white background
+               background = PIL.Image.new("RGBA", image.size, (255,255,255))
+
+               # Convert image to RGBA if not in RGBA, yet
+               if not image.mode == "RGBA":
+                       image = image.convert("RGBA")
+
+               # Flatten both images together
+               flattened_image = PIL.Image.alpha_composite(background, image)
+
+               # Remove the alpha channel
+               image = flattened_image.convert("RGB")
+
+       # Resize the image to the desired resolution
+       image.thumbnail((size, size), PIL.Image.LANCZOS)
+
+       if image.format == "JPEG":
+               # Apply a gaussian blur to make compression easier
+               image = image.filter(PIL.ImageFilter.GaussianBlur(radius=0.05))
+
+               # Arguments to optimise the compression
+               args.update({
+                       "subsampling" : "4:2:0",
+                       "quality"     : 70,
+               })
+
+       with io.BytesIO() as f:
+               # If writing out the image does not work with optimization,
+               # we try to write it out without any optimization.
+               try:
+                       image.save(f, format, optimize=True, **args)
+               except:
+                       image.save(f, format, **args)
+
+               return f.getvalue()
index b5aaa5fb86ae18d9c08e9500eb7511427cc2381d..c50d8ea1590900a248663f1ff8949003c91a4dfa 100644 (file)
@@ -1,9 +1,6 @@
 #!/usr/bin/python3
 
-import PIL
-import PIL.ImageFilter
 import difflib
-import io
 import logging
 import os.path
 import re
@@ -526,46 +523,9 @@ class File(misc.Object):
                        return thumbnail
 
                # Generate the thumbnail
-               thumbnail = self._generate_thumbnail(size)
+               thumbnail = util.generate_thumbnail(self.blob, size)
 
                # Put it into the cache for forever
                self.memcache.set(cache_key, thumbnail)
 
                return thumbnail
-
-       def _generate_thumbnail(self, size, **args):
-               image = PIL.Image.open(io.BytesIO(self.blob))
-
-               # Remove any alpha-channels
-               if image.format == "JPEG" and not image.mode == "RGB":
-                       # Make a white background
-                       background = PIL.Image.new("RGBA", image.size, (255,255,255))
-
-                       # Flatten both images together
-                       flattened_image = PIL.Image.alpha_composite(background, image)
-
-                       # Remove the alpha channel
-                       image = flattened_image.convert("RGB")
-
-               # Resize the image to the desired resolution
-               image.thumbnail((size, size), PIL.Image.LANCZOS)
-
-               if image.format == "JPEG":
-                       # Apply a gaussian blur to make compression easier
-                       image = image.filter(PIL.ImageFilter.GaussianBlur(radius=0.05))
-
-                       # Arguments to optimise the compression
-                       args.update({
-                               "subsampling" : "4:2:0",
-                               "quality"     : 70,
-                       })
-
-               with io.BytesIO() as f:
-                       # If writing out the image does not work with optimization,
-                       # we try to write it out without any optimization.
-                       try:
-                               image.save(f, image.format, optimize=True, **args)
-                       except:
-                               image.save(f, image.format, **args)
-
-                       return f.getvalue()