Resize/compress ``buf`` so it fits within IMAGE_TARGET_RAW_SIZE and IMAGE_MAX_WIDTH/HEIGHT. Returns the (possibly unchanged) buffer with media type and dimensions. On a hard Pillow failure (corrupt image), raises ``ImageProcessingError`` so the caller can decide whether to fall back
(
buf: bytes,
original_size: int,
format_hint: str | None = None,
)
| 240 | # --------------------------------------------------------------------------- |
| 241 | |
| 242 | def maybe_resize_image( |
| 243 | buf: bytes, |
| 244 | original_size: int, |
| 245 | format_hint: str | None = None, |
| 246 | ) -> ResizeResult: |
| 247 | """Resize/compress ``buf`` so it fits within IMAGE_TARGET_RAW_SIZE and |
| 248 | IMAGE_MAX_WIDTH/HEIGHT. |
| 249 | |
| 250 | Returns the (possibly unchanged) buffer with media type and dimensions. |
| 251 | On a hard Pillow failure (corrupt image), raises ``ImageProcessingError`` |
| 252 | so the caller can decide whether to fall back to the raw bytes. |
| 253 | |
| 254 | Mirrors TS imageResizer.ts:169-433. |
| 255 | """ |
| 256 | Image, UnidentifiedImageError = _pil() |
| 257 | |
| 258 | try: |
| 259 | img = Image.open(io.BytesIO(buf)) |
| 260 | img.load() # force decode now so we surface errors here |
| 261 | except UnidentifiedImageError as e: |
| 262 | _log_image_event("resize_failed", reason="unidentified", original_size=original_size) |
| 263 | raise ImageProcessingError(f"Could not decode image: {e}") from e |
| 264 | except Exception as e: |
| 265 | _log_image_event("resize_failed", reason="open_error", error=str(e), original_size=original_size) |
| 266 | raise ImageProcessingError(f"Could not open image: {e}") from e |
| 267 | |
| 268 | orig_w, orig_h = img.size |
| 269 | media_type = _pil_format_to_media_type(img.format, format_hint or "image/png") |
| 270 | |
| 271 | # Fast path: already within envelope, no work needed. |
| 272 | if ( |
| 273 | original_size <= IMAGE_TARGET_RAW_SIZE |
| 274 | and orig_w <= IMAGE_MAX_WIDTH |
| 275 | and orig_h <= IMAGE_MAX_HEIGHT |
| 276 | ): |
| 277 | return ResizeResult( |
| 278 | data=buf, |
| 279 | media_type=media_type, |
| 280 | dimensions=ImageDimensions( |
| 281 | original_width=orig_w, |
| 282 | original_height=orig_h, |
| 283 | display_width=orig_w, |
| 284 | display_height=orig_h, |
| 285 | ), |
| 286 | ) |
| 287 | |
| 288 | # Resize to fit IMAGE_MAX_WIDTH × IMAGE_MAX_HEIGHT, preserving aspect. |
| 289 | resized_img, new_w, new_h = _resize_to_envelope(img, IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT) |
| 290 | |
| 291 | # First encoding attempt at the original media type. |
| 292 | try: |
| 293 | encoded = _encode_image(resized_img, media_type) |
| 294 | except Exception as e: |
| 295 | _log_image_event("resize_failed", reason="encode_error", error=str(e)) |
| 296 | raise ImageProcessingError(f"Could not encode image: {e}") from e |
| 297 | |
| 298 | # If the resized+encoded version fits, ship it. |
| 299 | if len(encoded) <= IMAGE_TARGET_RAW_SIZE: |