# HG changeset patch # User Goffi # Date 1587307234 -7200 # Node ID 7aa01e262e058b9f68d76138e2d074767c9d0188 # Parent 704dada41df0ab75fd6c1bbcdbd5ffe81dbca1e6 plugin XEP-0054: SVG images can now be uploaded for avatars. diff -r 704dada41df0 -r 7aa01e262e05 sat/plugins/plugin_xep_0054.py --- 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