(image_path: Path, max_size_bytes: int = 5 * 1024 * 1024)
| 450 | |
| 451 | |
| 452 | def compress_image_if_needed(image_path: Path, max_size_bytes: int = 5 * 1024 * 1024) -> bytes: |
| 453 | image_path = Path(image_path) |
| 454 | actual_target = int(max_size_bytes * 0.75) |
| 455 | original_size = image_path.stat().st_size |
| 456 | |
| 457 | with Image.open(image_path) as img: |
| 458 | if img.mode != 'RGB': |
| 459 | img = img.convert('RGB') |
| 460 | width, height = img.size |
| 461 | if width > JPEG_MAX_DIMENSION or height > JPEG_MAX_DIMENSION: |
| 462 | logging.warning( |
| 463 | f"Image '{image_path}' has dimensions ({width}x{height}) " |
| 464 | f"exceeding JPEG limit. Resizing it down." |
| 465 | ) |
| 466 | aspect_ratio = width / height |
| 467 | if width > height: |
| 468 | new_width = JPEG_MAX_DIMENSION |
| 469 | new_height = int(new_width / aspect_ratio) |
| 470 | else: |
| 471 | new_height = JPEG_MAX_DIMENSION |
| 472 | new_width = int(new_height * aspect_ratio) |
| 473 | |
| 474 | |
| 475 | img = img.resize((new_width, new_height), Image.Resampling.LANCZOS) |
| 476 | logging.info(f"Resized to ({img.width}x{img.height})") |
| 477 | |
| 478 | |
| 479 | if original_size <= actual_target: |
| 480 | with open(image_path, 'rb') as f: |
| 481 | return f.read() |
| 482 | |
| 483 | |
| 484 | for quality in [85, 75, 65, 55, 45, 35, 25]: |
| 485 | buffer = io.BytesIO() |
| 486 | img.save(buffer, format='JPEG', quality=quality, optimize=True) |
| 487 | compressed_data = buffer.getvalue() |
| 488 | |
| 489 | if len(compressed_data) <= actual_target: |
| 490 | return compressed_data |
| 491 | |
| 492 | |
| 493 | current_width, current_height = img.size |
| 494 | for scale in [0.8, 0.6, 0.4, 0.2]: |
| 495 | new_width = int(current_width * scale) |
| 496 | new_height = int(current_height * scale) |
| 497 | resized_img = img.resize((new_width, new_height), Image.Resampling.LANCZOS) |
| 498 | |
| 499 | buffer = io.BytesIO() |
| 500 | resized_img.save(buffer, format='JPEG', quality=25, optimize=True) |
| 501 | compressed_data = buffer.getvalue() |
| 502 | |
| 503 | if len(compressed_data) <= actual_target: |
| 504 | return compressed_data |
| 505 | |
| 506 | |
| 507 | buffer = io.BytesIO() |
| 508 | resized_img.save(buffer, format='JPEG', quality=10, optimize=True) |
| 509 | return buffer.getvalue() |
no outgoing calls
no test coverage detected