afegit convertir-imagenes
This commit is contained in:
@@ -41,16 +41,17 @@ Las operaciones que tocan el contenido del archivo piden confirmación por defec
|
|||||||
|------|-------------|-------------------|
|
|------|-------------|-------------------|
|
||||||
| `--limpiar` | Elimina ficheros basura (`thumbs.db`, `.ds_store`, `__MACOSX`, `desktop.ini`) y reempaqueta como CBZ. | Sí |
|
| `--limpiar` | Elimina ficheros basura (`thumbs.db`, `.ds_store`, `__MACOSX`, `desktop.ini`) y reempaqueta como CBZ. | Sí |
|
||||||
| `--convertir` | Convierte al formato indicado por `--formato` (por defecto CBZ). | No |
|
| `--convertir` | Convierte al formato indicado por `--formato` (por defecto CBZ). | No |
|
||||||
| `--estandarizar` | Equivale a `--limpiar` + `--convertir` en secuencia. | Solo para limpieza |
|
| `--estandarizar` | Equivale a `--limpiar` + `--renumerar` + `--uniformizar-imagenes` + `--convertir` en secuencia. | Sí, salvo para conversión de formato |
|
||||||
| `--renumerar` | Renombra las páginas a numeración secuencial con zero-padding (`001.jpg`, `002.jpg`…). | Sí |
|
| `--renumerar` | Renombra las páginas a numeración secuencial con zero-padding (`001.jpg`, `002.jpg`…). | Sí |
|
||||||
| `--uniformizar-imagenes` | Convierte todas las imágenes al formato indicado por `--formato-imagen`. | Sí |
|
| `--uniformizar-imagenes` | Solo actúa si el archivo contiene imágenes en **formatos mixtos**. Si todas las imágenes ya son del mismo formato no hace nada, aunque no coincidan con `--formato-imagen`. | Sí |
|
||||||
|
| `--convertir-imagenes` | Convierte todas las imágenes que no sean `--formato-imagen`, independientemente de si los formatos ya son uniformes. | Sí |
|
||||||
|
|
||||||
### Opciones de formato
|
### Opciones de formato
|
||||||
|
|
||||||
| Flag | Valores | Por defecto | Descripción |
|
| Flag | Valores | Por defecto | Descripción |
|
||||||
|------|---------|-------------|-------------|
|
|------|---------|-------------|-------------|
|
||||||
| `--formato` | `cbz`, `cbr` | `cbz` | Formato de archivo destino para `--convertir` y `--estandarizar`. |
|
| `--formato` | `cbz`, `cbr` | `cbz` | Formato de archivo destino para `--convertir` y `--estandarizar`. |
|
||||||
| `--formato-imagen` | `jpg`, `png`, `webp` | `png` | Formato de imagen destino para `--uniformizar-imagenes`. |
|
| `--formato-imagen` | `jpg`, `png`, `webp` | `png` | Formato de imagen destino para `--uniformizar-imagenes` y `--convertir-imagenes`. |
|
||||||
| `--no-preguntar` | — | — | Desactiva la confirmación interactiva: aplica todas las operaciones automáticamente. |
|
| `--no-preguntar` | — | — | Desactiva la confirmación interactiva: aplica todas las operaciones automáticamente. |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
+14
-2
@@ -48,10 +48,22 @@ def extract_archive(path: str, dest_dir: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def repack_as_cbz(source_dir: str, target_path: str) -> None:
|
def repack_as_cbz(source_dir: str, target_path: str) -> None:
|
||||||
"""Empaqueta todos los archivos de source_dir en un CBZ (ZIP deflated)."""
|
"""Empaqueta todos los archivos de source_dir en un CBZ (ZIP deflated).
|
||||||
with zipfile.ZipFile(target_path, "w", zipfile.ZIP_DEFLATED) as zf:
|
|
||||||
|
Escribe primero a un fichero temporal (.tmp) en el mismo directorio y
|
||||||
|
hace un os.replace() atómico al final, de modo que una interrupción
|
||||||
|
nunca deja un CBZ parcial ni destruye el original.
|
||||||
|
"""
|
||||||
|
tmp_path = target_path + ".tmp"
|
||||||
|
try:
|
||||||
|
with zipfile.ZipFile(tmp_path, "w", zipfile.ZIP_DEFLATED) as zf:
|
||||||
for root, _, files in os.walk(source_dir):
|
for root, _, files in os.walk(source_dir):
|
||||||
for f in files:
|
for f in files:
|
||||||
full = os.path.join(root, f)
|
full = os.path.join(root, f)
|
||||||
rel = os.path.relpath(full, source_dir)
|
rel = os.path.relpath(full, source_dir)
|
||||||
zf.write(full, rel)
|
zf.write(full, rel)
|
||||||
|
os.replace(tmp_path, target_path)
|
||||||
|
except BaseException:
|
||||||
|
if os.path.exists(tmp_path):
|
||||||
|
os.remove(tmp_path)
|
||||||
|
raise
|
||||||
|
|||||||
+23
-1
@@ -17,7 +17,12 @@ from processors.checks import (
|
|||||||
check_comicinfo,
|
check_comicinfo,
|
||||||
)
|
)
|
||||||
from processors.page_normalizer import normalize_pages, preview_normalize_pages
|
from processors.page_normalizer import normalize_pages, preview_normalize_pages
|
||||||
from processors.image_normalizer import normalize_images, preview_normalize_images
|
from processors.image_normalizer import (
|
||||||
|
normalize_images,
|
||||||
|
preview_normalize_images,
|
||||||
|
uniformize_images,
|
||||||
|
preview_uniformize_images,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Pipeline:
|
class Pipeline:
|
||||||
@@ -50,6 +55,10 @@ class Pipeline:
|
|||||||
return {"renames": renames}
|
return {"renames": renames}
|
||||||
|
|
||||||
elif step == "normalize_images":
|
elif step == "normalize_images":
|
||||||
|
conversions = preview_uniformize_images(temp_dir, self.desired_image_format)
|
||||||
|
return {"conversions": conversions, "target_ext": self.desired_image_format}
|
||||||
|
|
||||||
|
elif step == "convert_images":
|
||||||
conversions = preview_normalize_images(temp_dir, self.desired_image_format)
|
conversions = preview_normalize_images(temp_dir, self.desired_image_format)
|
||||||
return {"conversions": conversions, "target_ext": self.desired_image_format}
|
return {"conversions": conversions, "target_ext": self.desired_image_format}
|
||||||
|
|
||||||
@@ -107,6 +116,19 @@ class Pipeline:
|
|||||||
preview = self._compute_preview("normalize_images", temp_dir, step_results)
|
preview = self._compute_preview("normalize_images", temp_dir, step_results)
|
||||||
if preview.get("conversions"):
|
if preview.get("conversions"):
|
||||||
if confirm_fn is None or confirm_fn("normalize_images", preview):
|
if confirm_fn is None or confirm_fn("normalize_images", preview):
|
||||||
|
img_result = uniformize_images(temp_dir, self.desired_image_format)
|
||||||
|
step_results.append(img_result)
|
||||||
|
if img_result.errors:
|
||||||
|
return ComicResult(
|
||||||
|
original_path=path, final_path=None, steps=step_results
|
||||||
|
)
|
||||||
|
if img_result.changed:
|
||||||
|
any_changed = True
|
||||||
|
|
||||||
|
if "convert_images" in self.steps:
|
||||||
|
preview = self._compute_preview("convert_images", temp_dir, step_results)
|
||||||
|
if preview.get("conversions"):
|
||||||
|
if confirm_fn is None or confirm_fn("convert_images", preview):
|
||||||
img_result = normalize_images(temp_dir, self.desired_image_format)
|
img_result = normalize_images(temp_dir, self.desired_image_format)
|
||||||
step_results.append(img_result)
|
step_results.append(img_result)
|
||||||
if img_result.errors:
|
if img_result.errors:
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ def _print_preview(step: str, preview: dict, formato: str) -> None:
|
|||||||
print(f" ... y {n - 10} más")
|
print(f" ... y {n - 10} más")
|
||||||
print(f"Formato final del archivo: {fmt}")
|
print(f"Formato final del archivo: {fmt}")
|
||||||
|
|
||||||
elif step == "normalize_images":
|
elif step in ("normalize_images", "convert_images"):
|
||||||
conversions = preview["conversions"]
|
conversions = preview["conversions"]
|
||||||
target_ext = preview["target_ext"].lstrip(".")
|
target_ext = preview["target_ext"].lstrip(".")
|
||||||
lossless = " (sin pérdida)" if target_ext.lower() == "png" else ""
|
lossless = " (sin pérdida)" if target_ext.lower() == "png" else ""
|
||||||
@@ -65,6 +65,7 @@ def parse_args():
|
|||||||
parser.add_argument("--formato", choices=["cbz", "cbr"], default="cbz")
|
parser.add_argument("--formato", choices=["cbz", "cbr"], default="cbz")
|
||||||
parser.add_argument("--renumerar", action="store_true")
|
parser.add_argument("--renumerar", action="store_true")
|
||||||
parser.add_argument("--uniformizar-imagenes", action="store_true")
|
parser.add_argument("--uniformizar-imagenes", action="store_true")
|
||||||
|
parser.add_argument("--convertir-imagenes", action="store_true")
|
||||||
parser.add_argument("--formato-imagen", choices=["jpg", "png", "webp"], default="png")
|
parser.add_argument("--formato-imagen", choices=["jpg", "png", "webp"], default="png")
|
||||||
|
|
||||||
parser.add_argument("--no-preguntar", action="store_true")
|
parser.add_argument("--no-preguntar", action="store_true")
|
||||||
@@ -94,10 +95,12 @@ def main():
|
|||||||
steps = []
|
steps = []
|
||||||
if args.limpiar or args.estandarizar:
|
if args.limpiar or args.estandarizar:
|
||||||
steps.append("clean")
|
steps.append("clean")
|
||||||
if args.renumerar:
|
if args.renumerar or args.estandarizar:
|
||||||
steps.append("normalize_pages")
|
steps.append("normalize_pages")
|
||||||
if args.uniformizar_imagenes:
|
if args.uniformizar_imagenes or args.estandarizar:
|
||||||
steps.append("normalize_images")
|
steps.append("normalize_images")
|
||||||
|
if args.convertir_imagenes:
|
||||||
|
steps.append("convert_images")
|
||||||
if args.convertir or args.estandarizar:
|
if args.convertir or args.estandarizar:
|
||||||
steps.append("convert")
|
steps.append("convert")
|
||||||
|
|
||||||
|
|||||||
@@ -87,3 +87,29 @@ def normalize_images(work_dir: str, target_ext: str = ".jpg") -> StepResult:
|
|||||||
changed = True
|
changed = True
|
||||||
|
|
||||||
return StepResult(step="normalize_images", changed=changed, details=details)
|
return StepResult(step="normalize_images", changed=changed, details=details)
|
||||||
|
|
||||||
|
|
||||||
|
def _detected_formats(work_dir: str) -> set[str]:
|
||||||
|
"""Devuelve el conjunto de extensiones de imagen presentes en work_dir (normalizando .jpeg → .jpg)."""
|
||||||
|
formats = set()
|
||||||
|
for fname in os.listdir(work_dir):
|
||||||
|
ext = os.path.splitext(fname)[1].lower()
|
||||||
|
if ext == ".jpeg":
|
||||||
|
ext = ".jpg"
|
||||||
|
if ext in IMAGE_EXTENSIONS:
|
||||||
|
formats.add(ext)
|
||||||
|
return formats
|
||||||
|
|
||||||
|
|
||||||
|
def preview_uniformize_images(work_dir: str, target_ext: str) -> list[tuple[str, str]]:
|
||||||
|
"""Como preview_normalize_images pero devuelve [] si las imágenes ya son uniformes."""
|
||||||
|
if len(_detected_formats(work_dir)) <= 1:
|
||||||
|
return []
|
||||||
|
return preview_normalize_images(work_dir, target_ext)
|
||||||
|
|
||||||
|
|
||||||
|
def uniformize_images(work_dir: str, target_ext: str = ".jpg") -> StepResult:
|
||||||
|
"""Como normalize_images pero solo actúa si hay formatos mixtos."""
|
||||||
|
if len(_detected_formats(work_dir)) <= 1:
|
||||||
|
return StepResult(step="normalize_images", changed=False)
|
||||||
|
return normalize_images(work_dir, target_ext)
|
||||||
|
|||||||
Reference in New Issue
Block a user