From 97396995d72b1d9c269d5753e48c75c03c7f8e3d Mon Sep 17 00:00:00 2001 From: Stephen Paul Weber Date: Tue, 28 Feb 2023 00:33:02 -0500 Subject: [PATCH] Convert APNG to WebP Signal uses APNG for animated stickers, but this is not supported in our apps so convert to WebP. --- guix.scm | 26 ++++++++++++++++++++++++++ main.py | 22 ++++++++++++++++++---- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/guix.scm b/guix.scm index e37487c..8377786 100644 --- a/guix.scm +++ b/guix.scm @@ -10,9 +10,34 @@ (gnu packages python-crypto) (gnu packages python-web) (gnu packages python-xyz) + (gnu packages fontutils) + (gnu packages image) (ice-9 rdelim) (ice-9 popen)) +(define-public python-pillow-mine + (package + (inherit python-pillow) + (name "python-pillow-mine") + (version "9.0.0.post1") + (source + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/singpolyma/Pillow") + (commit "float"))) + (file-name (git-file-name name version)) + (sha256 + (base32 "12zhlhqq8vxykndgsppwvgvyn0vnzbjfkc2kj8nh4r80lqjw916g")))) + (inputs + (modify-inputs (package-inputs python-pillow) + (prepend libraqm libimagequant))) + (arguments '(#:tests? #f)) + (home-page "https://github.com/uploadcare/pillow-simd") + (synopsis "Fork of the Python Imaging Library (Pillow)") + (description "This package is a fork of Pillow which adds support for SIMD +parallelism."))) + (define-public python-pymultihash (package (name "python-pymultihash") @@ -118,6 +143,7 @@ python-aiohttp python-pymultihash python-magic + python-pillow-mine python-signalstickers-client)) (home-page "https://git.singpolyma.net/signal-sticker-proxy") (synopsis "") diff --git a/main.py b/main.py index 7d595f8..963f3c6 100644 --- a/main.py +++ b/main.py @@ -3,8 +3,17 @@ import multihash import base58 import magic import sys +import io from aiohttp import web from signalstickers_client import StickersClient +from PIL import Image + +def to_webp(bytes): + out = io.BytesIO() + im = Image.open(io.BytesIO(bytes)) + im.apply_transparency() + im.save(out, format='WEBP', save_all=True, lossless=True, minimize_size=True, optimize=True) + return out.getvalue() async def get_pack(request): pack_id = request.match_info.get('pack') @@ -14,15 +23,18 @@ async def get_pack(request): pack = await client.get_pack(pack_id, key) stickers = [] for sticker in pack.stickers: + image_data = sticker.image_data + if magic.from_buffer(image_data, mime=True) != 'image/webp': + image_data = to_webp(image_data) stickers.append({ 'url': str(request.url) + "/" + str(sticker.id), 'pack': pack.title, 'name': sticker.emoji, 'copyright': pack.author, 'cids': [ - 'z' + base58.b58encode(b'\x01\x55' + multihash.digest(sticker.image_data, 'sha1').encode()).decode('utf-8'), - 'z' + base58.b58encode(b'\x01\x55' + multihash.digest(sticker.image_data, 'sha2-256').encode()).decode('utf-8'), - 'z' + base58.b58encode(b'\x01\x55' + multihash.digest(sticker.image_data, 'sha2-512').encode()).decode('utf-8') + 'z' + base58.b58encode(b'\x01\x55' + multihash.digest(image_data, 'sha1').encode()).decode('utf-8'), + 'z' + base58.b58encode(b'\x01\x55' + multihash.digest(image_data, 'sha2-256').encode()).decode('utf-8'), + 'z' + base58.b58encode(b'\x01\x55' + multihash.digest(image_data, 'sha2-512').encode()).decode('utf-8') ] }) return web.json_response(stickers) @@ -34,8 +46,10 @@ async def get_sticker(request): async with StickersClient() as client: image_data = await client.download_sticker(sticker_id, pack_id, key) + if magic.from_buffer(image_data, mime=True) != 'image/webp': + image_data = to_webp(image_data) result = web.Response(body=image_data) - result.headers['Content-Type'] = magic.from_buffer(image_data, mime=True) + result.headers['Content-Type'] = 'image/webp' return result app = web.Application() -- 2.38.5