Spaces:
Paused
Paused
Update app.py
Browse files
app.py
CHANGED
|
@@ -299,7 +299,7 @@ from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
| 299 |
def handle_batch(workbook_path, fmt, w, h):
|
| 300 |
if workbook_path is None:
|
| 301 |
return [], None, 'β Upload a workbook first.'
|
| 302 |
-
|
| 303 |
tmpdir = tempfile.mkdtemp()
|
| 304 |
outdir = os.path.join(tmpdir, 'out')
|
| 305 |
os.makedirs(outdir, exist_ok=True)
|
|
@@ -315,6 +315,7 @@ def handle_batch(workbook_path, fmt, w, h):
|
|
| 315 |
shutil.rmtree(tmpdir)
|
| 316 |
return [], None, 'β No URLs found.'
|
| 317 |
|
|
|
|
| 318 |
tasks = []
|
| 319 |
for code, url, _ in jobs:
|
| 320 |
idx = sum(1 for t in tasks if t[0] == code)
|
|
@@ -323,9 +324,8 @@ def handle_batch(workbook_path, fmt, w, h):
|
|
| 323 |
dl_path = os.path.join(outdir, f"{code}{suf}{ext_in}")
|
| 324 |
tasks.append((code, url, dl_path, suf))
|
| 325 |
|
| 326 |
-
# Download
|
| 327 |
future_to_task = {}
|
| 328 |
-
|
| 329 |
with ThreadPoolExecutor(max_workers=min(32, CPU_CORES * 2)) as ex:
|
| 330 |
for code, url, dl_path, suf in tasks:
|
| 331 |
fut = ex.submit(download_image_fast, url, dl_path, fail_log, code, suf)
|
|
@@ -342,14 +342,19 @@ def handle_batch(workbook_path, fmt, w, h):
|
|
| 342 |
if not os.path.exists(dl_path):
|
| 343 |
continue
|
| 344 |
try:
|
| 345 |
-
img = Image.open(dl_path)
|
| 346 |
-
|
| 347 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 348 |
out_p = os.path.join(outdir, out_fn)
|
| 349 |
|
| 350 |
if fmt.upper() == "JPEG":
|
| 351 |
-
|
| 352 |
-
final_jpg.save(out_p, "JPEG", quality=95, optimize=True, progressive=True)
|
| 353 |
else:
|
| 354 |
final.save(out_p, fmt.upper())
|
| 355 |
|
|
@@ -358,15 +363,16 @@ def handle_batch(workbook_path, fmt, w, h):
|
|
| 358 |
log_failure(fail_log, f"{code}{suf}: process error: {e}")
|
| 359 |
|
| 360 |
if not processed:
|
| 361 |
-
|
|
|
|
| 362 |
|
| 363 |
-
#
|
| 364 |
zip_path = os.path.join(tmpdir, "images.zip")
|
| 365 |
with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zipf:
|
| 366 |
-
for
|
| 367 |
-
zipf.write(
|
| 368 |
|
| 369 |
-
return processed, zip_path, f"β
Processed {len(processed)}
|
| 370 |
|
| 371 |
def handle_single_upload(uploaded_file, fmt, w, h):
|
| 372 |
if not uploaded_file: return None, None, "β No file."
|
|
|
|
| 299 |
def handle_batch(workbook_path, fmt, w, h):
|
| 300 |
if workbook_path is None:
|
| 301 |
return [], None, 'β Upload a workbook first.'
|
| 302 |
+
|
| 303 |
tmpdir = tempfile.mkdtemp()
|
| 304 |
outdir = os.path.join(tmpdir, 'out')
|
| 305 |
os.makedirs(outdir, exist_ok=True)
|
|
|
|
| 315 |
shutil.rmtree(tmpdir)
|
| 316 |
return [], None, 'β No URLs found.'
|
| 317 |
|
| 318 |
+
# Prepare download tasks
|
| 319 |
tasks = []
|
| 320 |
for code, url, _ in jobs:
|
| 321 |
idx = sum(1 for t in tasks if t[0] == code)
|
|
|
|
| 324 |
dl_path = os.path.join(outdir, f"{code}{suf}{ext_in}")
|
| 325 |
tasks.append((code, url, dl_path, suf))
|
| 326 |
|
| 327 |
+
# Download images
|
| 328 |
future_to_task = {}
|
|
|
|
| 329 |
with ThreadPoolExecutor(max_workers=min(32, CPU_CORES * 2)) as ex:
|
| 330 |
for code, url, dl_path, suf in tasks:
|
| 331 |
fut = ex.submit(download_image_fast, url, dl_path, fail_log, code, suf)
|
|
|
|
| 342 |
if not os.path.exists(dl_path):
|
| 343 |
continue
|
| 344 |
try:
|
| 345 |
+
img = Image.open(dl_path).convert("RGBA") # ensure RGBA for transparency-safe conversion
|
| 346 |
+
|
| 347 |
+
if fmt.upper() == "JPEG":
|
| 348 |
+
final = convert_to_jpeg(img, target=w)
|
| 349 |
+
else:
|
| 350 |
+
final = resize_and_pad(img.convert("RGB"), max_size=w)
|
| 351 |
+
|
| 352 |
+
out_ext = f".jpg" if fmt.upper() == "JPEG" else f".{fmt.lower()}"
|
| 353 |
+
out_fn = f"{code}{suf}{out_ext}"
|
| 354 |
out_p = os.path.join(outdir, out_fn)
|
| 355 |
|
| 356 |
if fmt.upper() == "JPEG":
|
| 357 |
+
final.save(out_p, "JPEG", quality=95, optimize=True, progressive=True, subsampling=0)
|
|
|
|
| 358 |
else:
|
| 359 |
final.save(out_p, fmt.upper())
|
| 360 |
|
|
|
|
| 363 |
log_failure(fail_log, f"{code}{suf}: process error: {e}")
|
| 364 |
|
| 365 |
if not processed:
|
| 366 |
+
shutil.rmtree(tmpdir)
|
| 367 |
+
return [], None, 'β No images processed.'
|
| 368 |
|
| 369 |
+
# Create ZIP of results
|
| 370 |
zip_path = os.path.join(tmpdir, "images.zip")
|
| 371 |
with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zipf:
|
| 372 |
+
for p in processed:
|
| 373 |
+
zipf.write(p, os.path.basename(p))
|
| 374 |
|
| 375 |
+
return processed, zip_path, f"β
Processed {len(processed)} image(s)."
|
| 376 |
|
| 377 |
def handle_single_upload(uploaded_file, fmt, w, h):
|
| 378 |
if not uploaded_file: return None, None, "β No file."
|