Mercurial > silorider
changeset 57:76dce7813340
Resize images if they're too large to be uploaded to Bluesky.
This adds a new dependency to the Pillow library.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Tue, 17 Oct 2023 15:34:26 -0700 |
parents | d5ba2179d876 |
children | d65f6dced79f |
files | requirements.txt setup.py silorider/silos/bluesky.py |
diffstat | 3 files changed, 35 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/requirements.txt Tue Oct 17 15:32:23 2023 -0700 +++ b/requirements.txt Tue Oct 17 15:34:26 2023 -0700 @@ -15,6 +15,7 @@ mf2py==1.1.2 mf2util==0.5.2 oauthlib==3.2.2 +Pillow==10.0.1 python-dateutil==2.8.2 python-magic==0.4.27 pytz==2023.3
--- a/setup.py Tue Oct 17 15:32:23 2023 -0700 +++ b/setup.py Tue Oct 17 15:34:26 2023 -0700 @@ -16,6 +16,7 @@ 'Mastodon.py>=1.3.0', 'mf2py>=1.1.0', 'mf2util>=0.5.0', + 'Pillow>=10.0.1', 'python-dateutil>=2.7.0', 'python-facebook-api>=0.17.1', 'python-twitter>=3.4.0',
--- a/silorider/silos/bluesky.py Tue Oct 17 15:32:23 2023 -0700 +++ b/silorider/silos/bluesky.py Tue Oct 17 15:34:26 2023 -0700 @@ -1,4 +1,5 @@ import re +import os.path import json import time import urllib.parse @@ -11,6 +12,8 @@ import atproto import atproto.xrpc_client.models as atprotomodels +from PIL import Image + logger = logging.getLogger(__name__) @@ -51,6 +54,7 @@ SILO_TYPE = 'bluesky' _DEFAULT_SERVER = 'bsky.app' _CLIENT_CLASS = _BlueskyClient + _MAX_IMAGE_SIZE = 976560 def __init__(self, ctx): super().__init__(ctx) @@ -99,6 +103,7 @@ return card def mediaCallback(self, tmpfile, mt, url, desc): + tmpfile = self._ensureFileNotTooLarge(tmpfile) with open(tmpfile, 'rb') as tmpfp: data = tmpfp.read() @@ -110,6 +115,34 @@ desc = "" return atprotomodels.AppBskyEmbedImages.Image(alt=desc, image=upload.blob) + def _ensureFileNotTooLarge(self, path): + file_size = os.path.getsize(path) + if file_size <= self._MAX_IMAGE_SIZE: + return path + + loops = 0 + scale = 0.75 + path_no_ext, ext = os.path.splitext(path) + smaller_path = '%s_bsky%s' % (path_no_ext, ext) + with Image.open(path) as orig_im: + # Resize down 75% until we get below the size limit. + img_width, img_height = orig_im.size + while loops < 10: + logger.debug("Resizing '%s' by a factor of %f" % (path, scale)) + img_width = int(img_width * scale) + img_height = int(img_height * scale) + with orig_im.resize((img_width, img_height)) as smaller_im: + smaller_im.save(smaller_path) + + file_size = os.path.getsize(smaller_path) + if file_size <= self._MAX_IMAGE_SIZE: + return smaller_path + + scale = scale * scale + loops += 1 + + raise Exception("Can't reach a small enough image to upload!") + def postEntry(self, entry_card, media_ids, ctx): # Add images as an embed on the atproto record. embed = None