Spaces:
Sleeping
Sleeping
File size: 5,260 Bytes
cd922fb | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | import io
import subprocess
from PIL import Image, ImageOps
import cv2
import numpy as np
from pathlib import Path
import piexif
class ImageCompressor:
def __init__(self):
self.supported_formats = {'.jpg', '.jpeg', '.png', '.webp', '.gif', '.bmp', '.tiff'}
def compress(self, input_path, output_path, method="auto", **kwargs):
"""Main compression entry point"""
img = Image.open(input_path)
original_size = Path(input_path).stat().st_size
# Get original format
original_format = img.format
if method == "auto":
# Use AI analyzer to determine best method
from .ai_analyzer import ContentAnalyzer
analyzer = ContentAnalyzer()
_, strategy = analyzer.analyze(input_path)
method = strategy.get("method", "avif")
kwargs = {**kwargs, **strategy}
# Apply compression based on method
if method == "avif":
compressed = self._compress_avif(img, kwargs.get('quality', 75))
output_path = str(output_path).replace(Path(output_path).suffix, '.avif')
elif method == "webp_lossless":
compressed = self._compress_webp_lossless(img, kwargs.get('quality', 90))
output_path = str(output_path).replace(Path(output_path).suffix, '.webp')
elif method == "png_optimized":
compressed = self._compress_png_optimized(img, kwargs.get('colors', 256))
output_path = str(output_path).replace(Path(output_path).suffix, '.png')
elif method == "png_quantized":
compressed = self._compress_png_quantized(img, kwargs.get('colors', 128))
output_path = str(output_path).replace(Path(output_path).suffix, '.png')
elif method == "jpeg_high_quality":
compressed = self._compress_jpeg(img, kwargs.get('quality', 85))
output_path = str(output_path).replace(Path(output_path).suffix, '.jpg')
else:
# Default to WebP
compressed = self._compress_webp(img, kwargs.get('quality', 80))
output_path = str(output_path).replace(Path(output_path).suffix, '.webp')
# Save compressed image
with open(output_path, 'wb') as f:
f.write(compressed)
compressed_size = Path(output_path).stat().st_size
ratio = (1 - compressed_size / original_size) * 100
return output_path, ratio
def _compress_avif(self, img, quality=75):
"""AVIF compression - best for photos"""
output = io.BytesIO()
# Convert RGBA to RGB if needed (AVIF doesn't support alpha well)
if img.mode == 'RGBA':
background = Image.new('RGB', img.size, (255, 255, 255))
background.paste(img, mask=img.split()[-1])
img = background
# Save as AVIF (requires pillow-avif-plugin)
img.save(output, format='AVIF', quality=quality, speed=4)
return output.getvalue()
def _compress_webp_lossless(self, img, quality=90):
"""Lossless WebP for text/screenshots"""
output = io.BytesIO()
img.save(output, format='WEBP', lossless=True, quality=quality, method=6)
return output.getvalue()
def _compress_webp(self, img, quality=80):
"""Standard WebP compression"""
output = io.BytesIO()
img.save(output, format='WEBP', quality=quality, method=4)
return output.getvalue()
def _compress_png_optimized(self, img, colors=256):
"""PNG with color palette reduction"""
output = io.BytesIO()
# Convert to palette mode
if colors < 256:
img = img.quantize(colors=colors, method=Image.MEDIANCUT)
img.save(output, format='PNG', optimize=True)
else:
img.save(output, format='PNG', optimize=True)
return output.getvalue()
def _compress_png_quantized(self, img, colors=128):
"""Heavy PNG quantization for graphics"""
output = io.BytesIO()
# Reduce colors dramatically
img_quantized = img.quantize(colors=colors, method=Image.FASTOCTREE)
img_quantized.save(output, format='PNG', optimize=True)
return output.getvalue()
def _compress_jpeg(self, img, quality=85):
"""JPEG compression"""
output = io.BytesIO()
# Convert to RGB if needed
if img.mode in ('RGBA', 'LA', 'P'):
img = img.convert('RGB')
img.save(output, format='JPEG', quality=quality, optimize=True, progressive=True)
return output.getvalue()
def smart_resize(self, img, target_dimension=2048):
"""Intelligently resize if image is too large"""
width, height = img.size
max_dim = max(width, height)
if max_dim > target_dimension:
scale = target_dimension / max_dim
new_size = (int(width * scale), int(height * scale))
return img.resize(new_size, Image.Resampling.LANCZOS)
return img
def remove_metadata(self, image_path):
"""Strip all EXIF metadata"""
piexif.remove(str(image_path)) |