84 lines
2.8 KiB
Python
84 lines
2.8 KiB
Python
# processors/page_normalizer.py
|
|
|
|
import os
|
|
import re
|
|
|
|
from core.constants import IMAGE_EXTENSIONS
|
|
from core.result import StepResult
|
|
|
|
|
|
def _natural_sort_key(name: str):
|
|
parts = re.split(r"(\d+)", name)
|
|
return [int(p) if p.isdigit() else p.lower() for p in parts]
|
|
|
|
|
|
def preview_normalize_pages(work_dir: str) -> list[tuple[str, str]]:
|
|
"""Devuelve lista de (nombre_actual, nombre_final) sin modificar nada."""
|
|
images = []
|
|
for root, _, files in os.walk(work_dir):
|
|
for f in files:
|
|
ext = os.path.splitext(f)[1].lower()
|
|
if ext in IMAGE_EXTENSIONS:
|
|
images.append(os.path.join(root, f))
|
|
|
|
images.sort(key=lambda p: _natural_sort_key(os.path.splitext(os.path.basename(p))[0]))
|
|
total = len(images)
|
|
if total == 0:
|
|
return []
|
|
|
|
width = len(str(total))
|
|
result = []
|
|
for i, src in enumerate(images):
|
|
ext = os.path.splitext(src)[1].lower()
|
|
original_name = os.path.basename(src)
|
|
final_name = f"{str(i + 1).zfill(width)}{ext}"
|
|
if original_name != final_name:
|
|
result.append((original_name, final_name))
|
|
|
|
return result
|
|
|
|
|
|
def normalize_pages(work_dir: str) -> StepResult:
|
|
"""
|
|
Renombra las imágenes del cómic a una numeración secuencial con zero-padding.
|
|
Fase 1: renombra a nombres temporales para evitar colisiones.
|
|
Fase 2: renombra a 001.ext, 002.ext… con ancho = len(str(total)).
|
|
"""
|
|
# Recopilar imágenes con natural sort
|
|
images = []
|
|
for root, _, files in os.walk(work_dir):
|
|
for f in files:
|
|
ext = os.path.splitext(f)[1].lower()
|
|
if ext in IMAGE_EXTENSIONS:
|
|
images.append(os.path.join(root, f))
|
|
|
|
images.sort(key=lambda p: _natural_sort_key(os.path.splitext(os.path.basename(p))[0]))
|
|
total = len(images)
|
|
if total == 0:
|
|
return StepResult(step="normalize_pages", changed=False)
|
|
|
|
width = len(str(total))
|
|
|
|
# Fase 1: renombrar a temporales para evitar colisiones intermedias
|
|
temp_paths = []
|
|
for i, src in enumerate(images):
|
|
ext = os.path.splitext(src)[1].lower()
|
|
tmp = os.path.join(os.path.dirname(src), f".tmp_rename_{i}{ext}")
|
|
os.rename(src, tmp)
|
|
temp_paths.append(tmp)
|
|
|
|
# Fase 2: renombrar a nombre final
|
|
changed = False
|
|
details = []
|
|
for i, tmp in enumerate(temp_paths):
|
|
ext = os.path.splitext(tmp)[1].lower()
|
|
final_name = f"{str(i + 1).zfill(width)}{ext}"
|
|
final_path = os.path.join(os.path.dirname(tmp), final_name)
|
|
os.rename(tmp, final_path)
|
|
original_name = os.path.basename(images[i])
|
|
if original_name != final_name:
|
|
details.append(f"{original_name} → {final_name}")
|
|
changed = True
|
|
|
|
return StepResult(step="normalize_pages", changed=changed, details=details)
|