Tabla de contenidos
0) Crea un entorno de desarrollo
Antes de ejecutar nada, es buena práctica trabajar dentro de un entorno virtual de Python.
Crea una carpeta de proyecto y un entorno de desarrollo:
mkdir aplicaciones_python
cd aplicaciones_python
# Crea el entorno virtual
python3 -m venv .venv
# Actívalo (Linux/Mac)
source .venv/bin/activate
# En Windows PowerShell
.venv\Scripts\activate
1) Requisitos
- Python 3.9+
- Pillow
pip install pillow
2) Guarda el script
Crea un fichero llamado resize_thumb.py con este contenido:
#!/usr/bin/env python3
import argparse
from pathlib import Path
from PIL import Image, ImageOps
THUMB_THRESHOLD = 1200 # si el ancho > 1200px, se crea .thumb
THUMB_WIDTH = 600 # ancho del thumbnail
SUFFIX = ".thumb"
EXTS = {".jpg", ".jpeg", ".png", ".webp", ".tif", ".tiff"}
def thumb_name(p: Path) -> Path:
return p.with_name(p.stem + SUFFIX + p.suffix.lower())
def save_image(img, out, fmt):
fmt = (fmt or p.suffix.lstrip(".")).upper()
if fmt in ("JPEG","JPG"):
img.save(out, format="JPEG", quality=80, optimize=True, progressive=True)
elif fmt == "PNG":
img.save(out, format="PNG", optimize=True)
elif fmt == "WEBP":
img.save(out, format="WEBP", quality=80, method=6)
else:
img.save(out)
def process(p: Path):
try:
with Image.open(p) as im:
im = ImageOps.exif_transpose(im) # respeta orientación EXIF
w, h = im.size
if w <= THUMB_THRESHOLD:
return
r = THUMB_WIDTH / float(w)
new = (THUMB_WIDTH, max(1, int(h * r)))
out_img = im.resize(new, Image.Resampling.LANCZOS)
out_path = thumb_name(p)
if out_path.exists() and out_path.stat().st_mtime >= p.stat().st_mtime:
return # ya existe y está actualizado
save_image(out_img, out_path, im.format)
print(f"Thumbnail: {out_path.name} {new[0]}x{new[1]}")
except Exception as e:
print(f"Error con {p}: {e}")
def main():
ap = argparse.ArgumentParser(description="Genera .thumb si el ancho > 1200px.")
ap.add_argument("--folder", required=True, help="Carpeta con imágenes")
args = ap.parse_args()
folder = Path(args.folder).expanduser().resolve()
if not folder.is_dir():
print("Carpeta no válida"); return
for p in sorted(folder.iterdir()):
if p.is_file() and p.suffix.lower() in EXTS and SUFFIX not in p.stem:
process(p)
if __name__ == "__main__":
main()
Personaliza
THUMB_THRESHOLD,THUMB_WIDTHySUFFIXsi lo necesitas.
3) Ejecutar
- Linux/macOS:
python3 resize_thumb.py --folder /ruta/a/imagenes
- Windows (PowerShell):
python .\resize_thumb.py --folder "C:\ruta\a\imagenes"
El script:
- Mantiene el original.
- Si el ancho > 1200 px, crea una copia proporcional con sufijo
.thumben la misma carpeta. - No re-procesa si la
.thumbya está al día. - Respeta la orientación EXIF.
4) Usarlo en tu HTML/CSS
Carga las miniaturas en la galería y enlaza al original si quieres lightbox:
<section id="galeria">
<a href="bosque1.jpg"><img src="bosque1.thumb.jpg" alt="Bosque 1"></a>
<a href="bosque2.jpg"><img src="bosque2.thumb.jpg" alt="Bosque 2"></a>
<!-- ... -->
</section>
CSS móvil first (básico):
#galeria img{
width: 100%;
aspect-ratio: 1/1;
object-fit: cover;
border-radius: 6px;
display: block;
margin-bottom: 10px;
}
5) Trucos útiles
- Procesar subcarpetas (bash):
find /ruta/imagenes -type d -maxdepth 1 -print0 | xargs -0 -I{} python3 resize_thumb.py --folder "{}"
- Ignorar ya generadas: el script lo hace por fecha (
mtime). - Formatos: JPG/PNG/WEBP/TIFF soportados.
6) Problemas típicos
- “No crea nada”: revisa que las imágenes superen
THUMB_THRESHOLD. - “No cambia el tamaño”: la
.thumbexiste y es más reciente que el original. - “Colores raros en PNG”: prueba
WEBPsi tu web lo soporta, o bajaqualityen JPEG.



