Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -7,6 +7,8 @@ import shutil
|
|
| 7 |
import logging
|
| 8 |
import base64
|
| 9 |
from concurrent.futures import ThreadPoolExecutor
|
|
|
|
|
|
|
| 10 |
|
| 11 |
from fastapi import FastAPI, UploadFile, File, Form, HTTPException
|
| 12 |
from fastapi.staticfiles import StaticFiles
|
|
@@ -151,24 +153,47 @@ def parse_srt(content: str):
|
|
| 151 |
|
| 152 |
return parsed
|
| 153 |
|
| 154 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 155 |
try:
|
| 156 |
img = Image.open(io.BytesIO(image_bytes))
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
if width > max_width:
|
| 162 |
-
height = int((height * max_width) / width)
|
| 163 |
-
width = max_width
|
| 164 |
-
img = img.resize((width, height), Image.Resampling.LANCZOS)
|
| 165 |
-
|
| 166 |
buffer = io.BytesIO()
|
| 167 |
-
|
| 168 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 169 |
return buffer.getvalue()
|
|
|
|
| 170 |
except Exception as e:
|
| 171 |
-
logger.error(f"
|
| 172 |
return None
|
| 173 |
|
| 174 |
def process_batch_gemini(api_key, items, model_name):
|
|
|
|
| 7 |
import logging
|
| 8 |
import base64
|
| 9 |
from concurrent.futures import ThreadPoolExecutor
|
| 10 |
+
from PIL import Image, ImageOps
|
| 11 |
+
|
| 12 |
|
| 13 |
from fastapi import FastAPI, UploadFile, File, Form, HTTPException
|
| 14 |
from fastapi.staticfiles import StaticFiles
|
|
|
|
| 153 |
|
| 154 |
return parsed
|
| 155 |
|
| 156 |
+
|
| 157 |
+
|
| 158 |
+
logger = logging.getLogger(__name__)
|
| 159 |
+
|
| 160 |
+
def compress_advanced(image_bytes, max_width=800, use_webp=True):
|
| 161 |
try:
|
| 162 |
img = Image.open(io.BytesIO(image_bytes))
|
| 163 |
+
|
| 164 |
+
# 1. Resize efficiently (using thumbnail is faster/safer than manual math)
|
| 165 |
+
img.thumbnail((max_width, max_width), Image.Resampling.LANCZOS)
|
| 166 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 167 |
buffer = io.BytesIO()
|
| 168 |
+
|
| 169 |
+
if use_webp:
|
| 170 |
+
# OPTION A: WebP (Best Balance)
|
| 171 |
+
# quality=80 in WebP looks like quality=90+ in JPEG but is much smaller
|
| 172 |
+
img.save(buffer, format="WEBP", quality=80, method=6)
|
| 173 |
+
else:
|
| 174 |
+
# OPTION B: Optimized JPEG (If you strictly need JPG)
|
| 175 |
+
# Handle transparency (paste on white) only for JPEG
|
| 176 |
+
if img.mode in ('RGBA', 'LA') or (img.mode == 'P' and 'transparency' in img.info):
|
| 177 |
+
background = Image.new('RGB', img.size, (255, 255, 255))
|
| 178 |
+
background.paste(img, mask=img.split()[3] if len(img.split()) > 3 else None)
|
| 179 |
+
img = background
|
| 180 |
+
elif img.mode != 'RGB':
|
| 181 |
+
img = img.convert('RGB')
|
| 182 |
+
|
| 183 |
+
# Advanced JPEG Optimization
|
| 184 |
+
img.save(
|
| 185 |
+
buffer,
|
| 186 |
+
format="JPEG",
|
| 187 |
+
quality=80,
|
| 188 |
+
optimize=True, # Extra pass to shrink file size
|
| 189 |
+
progressive=True, # Loads gradually on slow nets & usually smaller
|
| 190 |
+
subsampling=0 # Keeps edges sharp (4:4:4)
|
| 191 |
+
)
|
| 192 |
+
|
| 193 |
return buffer.getvalue()
|
| 194 |
+
|
| 195 |
except Exception as e:
|
| 196 |
+
logger.error(f"Compression failed: {e}")
|
| 197 |
return None
|
| 198 |
|
| 199 |
def process_batch_gemini(api_key, items, model_name):
|