changeset 3258:7aa01e262e05

plugin XEP-0054: SVG images can now be uploaded for avatars.
author Goffi <goffi@goffi.org>
date Sun, 19 Apr 2020 16:40:34 +0200
parents 704dada41df0
children f300d78f08f3
files sat/plugins/plugin_xep_0054.py
diffstat 1 files changed, 35 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/sat/plugins/plugin_xep_0054.py	Sun Apr 19 16:38:46 2020 +0200
+++ b/sat/plugins/plugin_xep_0054.py	Sun Apr 19 16:40:34 2020 +0200
@@ -331,36 +331,47 @@
 
     def _buildSetAvatar(self, client, vcard_elt, avatar_data):
         # XXX: this method is executed in a separate thread
-        try:
-            img = Image.open(avatar_data['path'])
-        except IOError as e:
-            raise exceptions.DataError(f"Can't open image: {e}")
+        if avatar_data["media_type"] == "image/svg+xml":
+            # for vector image, we save directly
+            img_buf = open(avatar_data["path"], "rb")
+        else:
+            # for bitmap image, we check size and resize if necessary
+            try:
+                img = Image.open(avatar_data["path"])
+            except IOError as e:
+                raise exceptions.DataError(f"Can't open image: {e}")
 
-        if img.size != AVATAR_DIM:
-            img.thumbnail(AVATAR_DIM)
-            if img.size[0] != img.size[1]:  # we need to crop first
-                left, upper = (0, 0)
-                right, lower = img.size
-                offset = abs(right - lower) / 2
-                if right == min(img.size):
-                    upper += offset
-                    lower -= offset
-                else:
-                    left += offset
-                    right -= offset
-                img = img.crop((left, upper, right, lower))
-        img_buf = io.BytesIO()
-        img.save(img_buf, "PNG")
+            if img.size != AVATAR_DIM:
+                img.thumbnail(AVATAR_DIM)
+                if img.size[0] != img.size[1]:  # we need to crop first
+                    left, upper = (0, 0)
+                    right, lower = img.size
+                    offset = abs(right - lower) / 2
+                    if right == min(img.size):
+                        upper += offset
+                        lower -= offset
+                    else:
+                        left += offset
+                        right -= offset
+                    img = img.crop((left, upper, right, lower))
+            img_buf = io.BytesIO()
+            # PNG is well supported among clients, so we convert to this format
+            img.save(img_buf, "PNG")
+            img_buf.seek(0)
+            avatar_data["media_type"] = "image/png"
 
+        media_type = avatar_data["media_type"]
         photo_elt = vcard_elt.addElement("PHOTO")
-        photo_elt.addElement("TYPE", content="image/png")
-        image_b64 = b64encode(img_buf.getvalue()).decode()
+        photo_elt.addElement("TYPE", content=media_type)
+        image_b64 = b64encode(img_buf.read()).decode()
+        img_buf.seek(0)
         photo_elt.addElement("BINVAL", content=image_b64)
-        image_hash = sha1(img_buf.getvalue()).hexdigest()
+        image_hash = sha1(img_buf.read()).hexdigest()
+        img_buf.seek(0)
         with self.host.common_cache.cacheData(
-            PLUGIN_INFO["import_name"], image_hash, "image/png"
+            PLUGIN_INFO["import_name"], image_hash, media_type
         ) as f:
-            f.write(img_buf.getvalue())
+            f.write(img_buf.read())
             avatar_data['path'] = Path(f.name)
         avatar_data['cache_uid'] = image_hash
         return image_hash