Saltar al contenido
Volver al inicio 100 Días de Código en Python — Día 85: Proyecto de portafolio — Aplicación de escritorio para agregar marcas de agua

100 Días de Código en Python — Día 85: Proyecto de portafolio — Aplicación de escritorio para agregar marcas de agua

Nivel: Grado décimo Área: Tecnología e Informática Modalidad: Tutorial práctico Fuente: Curso "100 Days of Code: The Complete Python Pro Bootcamp" (Angela Yu, App Brewery). Contenido del Día 85, proyecto de portafolio profesional (categoría GUI).

Este tutorial adapta pedagógicamente el Día 85. La sección 📝 Contenido original del curso proviene del único archivo de la carpeta: dia85-tarea4.md (enunciado y pregunta de reflexión, en inglés; aquí traducido). El curso no ofrece guía ni solución, y este tutorial no entrega la aplicación terminada: ofrece el análisis, las piezas de Pillow verificadas, un esqueleto de interfaz para completar, pruebas y retos. Todo lo que no está en ese archivo (conceptos de imágenes, capas y transparencia, código de ejemplo, sección de derechos de autor y privacidad, retos 🟢🟡🟠🔴, proyecto extra y la etapa 4 de Mi Portafolio Profesional) es creación de esta adaptación.

Nota sobre las verificaciones: el 28 de septiembre de 2026, con Python 3.14 y Pillow 12.3.0, se ejecutaron las funciones agregar_marca_texto y agregar_logo de la sección 4 sobre imágenes generadas para la prueba (800 × 600). También se comprobó que Image.ANTIALIAS y ImageDraw.textsize ya no existen en Pillow y que guardar una imagen RGBA como JPEG produce OSError: cannot write mode RGBA as JPEG. La interfaz Tkinter de la sección 5 es un esqueleto para completar y no se probó con clics reales.


Tabla de contenidos

  1. La tarea: marcas de agua automáticas
  2. Analizar el problema antes de programar
  3. 📖 Cómo "piensa" Pillow una imagen: modos, capas y transparencia
  4. 📖 La lógica: agregar texto y logo (sin interfaz)
  5. 📖 La interfaz: abrir, previsualizar y guardar con Tkinter
  6. 📖 Derechos de autor y privacidad de las imágenes
  7. 🚀 Proyecto del día: construcción por versiones
  8. 🌟 Proyecto extra: generador de carnés para un evento
  9. 🏗️ Mi Portafolio Profesional — Etapa 4
  10. 🧩 Comprueba lo aprendido
  11. 🤖 Programar con apoyo de IA
  12. 🛠️ Observaciones sobre el material original
  13. 📋 Matriz de trazabilidad
  14. 📦 Evidencias de aprendizaje del Día 85

1. La tarea: marcas de agua automáticas

(Fuente: dia85-tarea4.md)

📝 Contenido original del curso

Usando lo que aprendiste de Tkinter, crea una aplicación de escritorio con interfaz gráfica (GUI) en la que puedas cargar una imagen y usar Python para agregarle una marca de agua (un logo o un texto).

Normalmente tendrías que usar un programa de edición como Photoshop; tu programa lo hará automáticamente.

Caso de uso: quieres empezar a publicar tus fotos en Instagram, pero quieres que todas lleven tu sitio web. Con tu software puedes agregar tu sitio o logo automáticamente a cualquier imagen. Un servicio en línea parecido es watermarkly.com.

Quizá necesites: la librería Pillow (pypi.org/project/Pillow), la documentación de tkinter (docs.python.org) "y algo de Google".

Pregunta de la tarea — Momento de reflexión: cómo abordaste el proyecto; qué fue difícil y qué fácil; cómo mejorarías; tu mayor aprendizaje; qué harías distinto.

Prerequisitos: Tkinter: ventanas, botones, etiquetas, entradas y grid (Días 27–29); funciones y parámetros (Días 8 y 10); manejo de archivos y rutas (Día 24); excepciones (Día 30); instalar paquetes con pip (Día 15).


2. Analizar el problema antes de programar

(Sección creada para esta adaptación.)

🔍 Antes de programar

Pregunta Respuesta que debes construir tú
¿Qué información tenemos? Una imagen del usuario y un texto o logo
¿Qué necesitamos obtener del usuario? Qué imagen, qué texto (o qué logo), dónde ponerlo, qué tan transparente
¿Qué proceso se realiza? Abrir imagen → crear la marca → combinarlas → mostrar el resultado → guardarlo
¿Qué resultado esperamos? Un archivo nuevo con la marca; el original intacto
¿Qué condiciones hay que tener en cuenta? Imágenes grandes o pequeñas, fotos verticales, archivos que no son imágenes, PNG con transparencia

Dos capas separadas: lógica e interfaz

Un error típico es mezclar todo dentro de la función de un botón. Separa:

Texto
marcas.py (lógica, sin Tkinter)          app.py (interfaz)
┌───────────────────────────────┐        ┌──────────────────────────┐
│ agregar_marca_texto(...)      │ ◄───── │ botón "Aplicar"          │
│ agregar_logo(...)             │        │ botones "Abrir"/"Guardar"│
│ se prueba sin abrir ventanas  │        │ vista previa             │
└───────────────────────────────┘        └──────────────────────────┘

Ventaja: puedes probar marcas.py con assert y, en el futuro, reutilizarlo en una página web (Día 92) o en un script que procese una carpeta entera.


3. 📖 Cómo "piensa" Pillow una imagen: modos, capas y transparencia

(Sección creada para esta adaptación.)

🎯 Objetivo de aprendizaje

Explicar qué es el canal alfa y por qué la marca de agua se dibuja en una capa aparte.

📖 Explicación conceptual

Una imagen digital es una cuadrícula de píxeles. Cada píxel guarda números según el modo:

Modo Cada píxel guarda Ejemplo Formatos típicos
RGB Rojo, verde, azul (0–255) (30, 90, 160) JPEG, PNG
RGBA RGB + alfa (opacidad: 0 transparente, 255 opaco) (255, 255, 255, 128) = blanco semitransparente PNG (el JPEG no admite alfa)
L Un solo valor de gris 128 Ambos

Una marca de agua "semitransparente" es un texto con alfa intermedio (por ejemplo, 128). Para que la transparencia se mezcle bien con la foto:

  1. Convertir la foto a RGBA.
  2. Crear una capa del mismo tamaño, totalmente transparente.
  3. Dibujar el texto en esa capa.
  4. Componer ambas capas con Image.alpha_composite.

Es la misma idea de las capas de un editor de fotos.

Coordenadas: en Pillow (como en Tkinter y en turtle con otro origen), el punto (0, 0) es la esquina superior izquierda; x crece hacia la derecha y y hacia abajo.


4. 📖 La lógica: agregar texto y logo (sin interfaz)

(Sección creada para esta adaptación. Código verificado con Pillow 12.3.0.)

Instala Pillow en tu entorno virtual: pip install Pillow (el paquete se llama Pillow, pero se importa como PIL).

🔎 Ejemplo explicado: texto en la esquina inferior derecha

Python
from PIL import Image, ImageDraw, ImageFont

def agregar_marca_texto(ruta_entrada, ruta_salida, texto, opacidad=128):
    with Image.open(ruta_entrada) as original:
        imagen = original.convert("RGBA")
    capa = Image.new("RGBA", imagen.size, (255, 255, 255, 0))
    dibujo = ImageDraw.Draw(capa)

    tamano = max(12, imagen.width // 20)
    try:
        fuente = ImageFont.truetype("arial.ttf", tamano)
    except OSError:
        fuente = ImageFont.load_default(size=tamano)

    izquierda, arriba, derecha, abajo = dibujo.textbbox((0, 0), texto, font=fuente)
    ancho, alto = derecha - izquierda, abajo - arriba
    margen = tamano // 2
    posicion = (imagen.width - ancho - margen, imagen.height - alto - margen)

    dibujo.text(posicion, texto, font=fuente, fill=(255, 255, 255, opacidad))
    resultado = Image.alpha_composite(imagen, capa)
    resultado.convert("RGB").save(ruta_salida, "JPEG", quality=95)

Qué hace cada parte:

  • with Image.open(...) abre el archivo y lo cierra al terminar (Día 24).
  • Image.new("RGBA", imagen.size, (255, 255, 255, 0)): capa del mismo tamaño, blanca pero con alfa 0 (invisible).
  • tamano = imagen.width // 20: el texto se adapta a la imagen. Con un tamaño fijo, en una foto de 4000 px la marca sería diminuta y en una de 300 px, gigante.
  • ImageFont.truetype("arial.ttf", ...) busca la fuente Arial (existe en Windows). Si no la encuentra (Linux, macOS), load_default(size=...) usa la fuente incluida en Pillow. El try/except evita que el programa se cierre (Día 30).
  • textbbox((0, 0), texto, font=fuente) devuelve la "caja" que ocupa el texto: con ella se calcula dónde ubicarlo para que no se salga.
  • alpha_composite mezcla la foto y la capa respetando la transparencia.
  • .convert("RGB") antes de guardar como JPEG: el JPEG no acepta alfa.

La idea para un logo PNG con transparencia es parecida (verificada): abrir el logo en RGBA, redimensionarlo proporcionalmente (por ejemplo, al 20 % del ancho de la foto) con logo.resize((ancho, alto), Image.Resampling.LANCZOS) y pegarlo con imagen.paste(logo, posicion, logo). El tercer argumento (la máscara) hace que las partes transparentes del logo no tapen la foto.

Pregunta: si el logo mide 200 × 100 y quieres que tenga 160 px de ancho, ¿qué alto debe tener para no deformarse?

⚠️ Errores frecuentes

Error Qué ocurre Por qué Solución
OSError: cannot write mode RGBA as JPEG No se guarda la imagen El JPEG no tiene canal alfa .convert("RGB") antes de guardar, o guardar como PNG
AttributeError: ... has no attribute 'ANTIALIAS' Código de un tutorial antiguo falla Pillow 10 (2023) eliminó Image.ANTIALIAS Usa Image.Resampling.LANCZOS
AttributeError: ... 'textsize' Igual que el anterior Pillow 10 eliminó ImageDraw.textsize Usa textbbox o textlength
OSError: cannot open resource No encuentra la fuente La ruta de la fuente no existe en ese sistema try/except con load_default o incluye un .ttf con licencia libre en tu proyecto
El logo aparece con un fondo negro La transparencia se pierde Se pegó sin máscara imagen.paste(logo, pos, logo)
Se sobrescribe la foto original El usuario pierde su foto Se guardó con la misma ruta Guarda con otro nombre (foto_marca.jpg) o pregunta con "Guardar como"
La marca "desaparece" en fotos claras Texto blanco sobre cielo blanco Poco contraste Permite elegir color, o agrega una sombra (dibuja el texto dos veces, desplazado)

5. 📖 La interfaz: abrir, previsualizar y guardar con Tkinter

(Sección creada para esta adaptación. Esqueleto para completar; no se probó con clics reales.)

Tkinter trae los diálogos de archivos listos en tkinter.filedialog, y Pillow trae ImageTk para mostrar imágenes en la ventana.

Python
import tkinter as tk
from tkinter import filedialog, messagebox
from PIL import Image, ImageTk

ventana = tk.Tk()
ventana.title("Marca de agua")

ruta_actual = None
vista = tk.Label(ventana, text="Abre una imagen")
vista.grid(row=0, column=0, columnspan=3)

def abrir():
    global ruta_actual
    ruta = filedialog.askopenfilename(
        filetypes=[("Imágenes", "*.jpg *.jpeg *.png")])
    if not ruta:            # el usuario canceló
        return
    ruta_actual = ruta
    with Image.open(ruta) as imagen:
        miniatura = imagen.copy()
    miniatura.thumbnail((500, 500))           # no deforma la imagen
    foto = ImageTk.PhotoImage(miniatura)
    vista.config(image=foto, text="")
    vista.image = foto                         # ¡guardar una referencia!

tk.Button(ventana, text="Abrir imagen", command=abrir).grid(row=1, column=0)
# Tu turno: campo de texto, botón "Aplicar", botón "Guardar como"...

ventana.mainloop()

Puntos clave:

  • askopenfilename devuelve la ruta elegida o una cadena vacía si el usuario cancela: compruébalo.
  • thumbnail((500, 500)) reduce la imagen manteniendo la proporción, solo para mostrarla. La marca debe aplicarse a la imagen original, en su tamaño completo.
  • vista.image = foto: si no guardas una referencia a PhotoImage, Python la borra de la memoria y la imagen no se ve (la etiqueta queda en blanco sin mostrar error). Es uno de los errores más desconcertantes de Tkinter.
  • Para "Guardar como": filedialog.asksaveasfilename(defaultextension=".jpg").
  • Para avisar errores: messagebox.showerror("Error", "No se pudo abrir el archivo") dentro de un except.

Alternativa de diseño: en lugar de global ruta_actual, crear una clase AppMarcaDeAgua con atributos (Días 16–17). Con más de dos o tres variables compartidas, la clase es más ordenada. Compara ambas y elige.


6. 📖 Derechos de autor y privacidad de las imágenes

(Sección creada para esta adaptación.)

Una marca de agua sirve para identificar tu obra. Úsala de forma responsable:

✅ Adecuado ❌ No adecuado
Marcar tus fotos o las del club de fotografía, con permiso Poner tu marca sobre fotos de otras personas para hacerlas pasar por tuyas
Marcar imágenes con licencia que lo permita (revisa la licencia) Quitar marcas de agua ajenas: vulnera los derechos de autor
Probar con imágenes generadas por ti o paisajes Probar con fotos de compañeros sin su consentimiento

Privacidad: las fotos pueden llevar metadatos EXIF (fecha, modelo del celular e incluso coordenadas GPS). Al crear una imagen nueva con Pillow y guardarla sin pasar el EXIF, esos datos normalmente no se copian; compruébalo con las propiedades del archivo. Es una buena "característica de privacidad" para mencionar en tu README.md.


7. 🚀 Proyecto del día: construcción por versiones

(Desarrolla la tarea dia85-tarea4.md. Las versiones son una propuesta de esta adaptación.)

Problema

Construir una aplicación de escritorio que agregue una marca de agua (texto y/o logo) a una imagen.

Contexto

El club de fotografía del colegio publica las fotos de los eventos en su cuenta y quiere que todas lleven su nombre, sin tener que editarlas una por una.

Objetivo

Una aplicación Tkinter que abra una imagen, muestre una vista previa, aplique una marca configurable y guarde una copia.

Requisitos funcionales

  1. Abrir una imagen JPG o PNG con un diálogo de archivos.
  2. Escribir el texto de la marca y aplicarlo; ver el resultado en la vista previa.
  3. Guardar el resultado como archivo nuevo.
  4. Mostrar mensajes claros si algo falla (archivo no válido, nada que guardar).

Restricciones técnicas

  • Lógica de imágenes en un módulo separado de la interfaz (sección 2).
  • La marca debe escalar con el tamaño de la imagen.
  • Nunca sobrescribir la imagen original sin preguntar.

Planificación

  1. Comprender el caso de uso (prueba watermarkly.com o un editor). 2. Entradas: imagen, texto/logo, opciones. 3. Procesos: abrir → componer → mostrar → guardar. 4. Salidas: la vista previa y el archivo. 5. Dividir en lógica e interfaz. 6. Bocetar la ventana. 7. Implementar por versiones. 8. Probar. 9. Corregir. 10. Mejorar.

Construcción paso a paso

  • Versión 1 — Lógica en consola: marcas.py con agregar_marca_texto; pruébala con una imagen fija, sin ventanas.
  • Versión 2 — Ventana y vista previa: abrir una imagen y mostrar su miniatura.
  • Versión 3 — Aplicar texto: campo de texto y botón "Aplicar" que actualiza la vista previa.
  • Versión 4 — Guardar: "Guardar como" con el formato adecuado.
  • Versión 5 — Opciones: posición (menú con esquinas y centro), opacidad (tk.Scale), color.
  • Versión final — Logo y pulido: agregar logo PNG, mensajes de error, README.md con capturas antes/después, diario.

Pruebas

# Caso Resultado esperado
1 Foto horizontal grande (por ejemplo, 4000 × 3000) Marca visible y proporcionada
2 Foto vertical pequeña (300 × 500) La marca no se sale de la imagen
3 PNG con fondo transparente Se guarda sin error (convertir o guardar como PNG)
4 Abrir un archivo .txt renombrado como .jpg Mensaje de error, la app no se cierra
5 Cancelar el diálogo de abrir No pasa nada, no hay error
6 Texto vacío La app avisa o no aplica nada
7 Guardar y abrir el resultado con otro programa Se abre bien; el original no cambió

Prueba automática de la lógica (sin ventanas):

Python
from PIL import Image
from marcas import agregar_marca_texto

Image.new("RGB", (800, 600), (30, 90, 160)).save("prueba.jpg")
agregar_marca_texto("prueba.jpg", "prueba_marca.jpg", "@club_foto")
with Image.open("prueba_marca.jpg") as resultado:
    assert resultado.size == (800, 600)
    assert resultado.mode == "RGB"

🧪 Prueba y depuración

Python
def aplicar():
    imagen = Image.open(ruta_actual)
    dibujo = ImageDraw.Draw(imagen)
    dibujo.text((10, 10), entrada.get(), fill=(255, 255, 255, 100))
    imagen = imagen.resize((500, 500), Image.ANTIALIAS)
    foto = ImageTk.PhotoImage(imagen)
    vista.config(image=foto)
    imagen.save(ruta_actual)

Encuentra cinco problemas: el alfa no tiene efecto al dibujar directo sobre una imagen RGB (hace falta la capa y alpha_composite); ANTIALIAS ya no existe; resize((500, 500)) deforma la imagen (mejor thumbnail sobre una copia); no se guarda la referencia a foto; y se sobrescribe el original (¡con la versión reducida!).

⭐ Extensión del proyecto

  • 🟢 Reto 1 — Aplicación: agrega una sombra al texto para que se lea sobre fondos claros y oscuros.
  • 🟡 Reto 2 — Ampliación: marca de agua en mosaico (el texto repetido en diagonal por toda la imagen); pista: rota la capa con capa.rotate(...).
  • 🟠 Reto 3 — Desafío: procesamiento por lotes: elegir una carpeta (askdirectory) y marcar todas sus imágenes, guardándolas en una subcarpeta con_marca/ (Día 24: pathlib). Muestra el progreso.
  • 🔴 Reto 4 — Pensamiento computacional: diseña una forma de elegir automáticamente el color de la marca (blanco o negro) según el brillo de la zona donde irá. ¿Cómo mides el brillo de una región? (Pista: imagen.crop(...) y el promedio de sus píxeles en modo L.) Prueba tu regla con 5 fotos distintas.

8. 🌟 Proyecto extra: generador de carnés para un evento

(Proyecto creado para esta adaptación; no existe en el curso original.)

Situación

Para la feria de ciencia del colegio se necesitan carnés para los expositores: una plantilla con el logo de la feria, el nombre del expositor, su proyecto y su mesa.

Requisitos

  1. Leer los datos desde un CSV (nombre, proyecto, mesa) con csv o pandas (Día 25).
  2. Generar una imagen PNG por persona sobre una plantilla, centrando el texto (pista: textbbox).
  3. Una interfaz Tkinter para elegir la plantilla y el CSV y ver la vista previa del primer carné.

Decisiones que debes tomar (y justificar)

  • ¿Qué pasa con un nombre muy largo? ¿Reduces la fuente, lo cortas o lo divides en dos líneas?
  • ¿Cómo nombras los archivos para que no se repitan si hay dos personas con el mismo nombre?

Casos de prueba

  • Un nombre de 40 caracteres cabe en el carné.
  • Nombres con tildes y "ñ" se ven bien (la fuente debe tener esos caracteres).
  • Una fila del CSV sin mesa se reporta en lugar de generar un carné incompleto.

🏫 Usa datos ficticios para las pruebas; los datos reales de estudiantes solo con autorización.


9. 🏗️ Mi Portafolio Profesional — Etapa 4

(Proyecto integrador creado para esta adaptación; etapas anteriores en los Días 82 a 84.)

Etapa 4 (hoy):

  1. Repositorio de la app de marcas de agua con marcas.py, app.py, requirements.txt (con Pillow) y .gitignore (excluye imágenes de prueba personales).
  2. README.md con una captura de la interfaz y un antes/después con una imagen libre de derechos o propia.
  3. DIARIO.md del Día 85.
  4. Ficha en proyectos.json y comprobación en tu sitio. Ya tienes proyectos de consola y de GUI: revisa que las tarjetas de tu sitio muestren la categoría o las tecnologías.

10. 🧩 Comprueba lo aprendido

Conceptuales

  1. ¿Qué es el canal alfa? ¿Por qué el JPEG no sirve para guardar transparencia?
  2. ¿Por qué conviene separar la lógica de las imágenes de la interfaz?
  3. ¿Qué diferencia hay entre resize y thumbnail?
  4. ¿Por qué hay que guardar una referencia a PhotoImage en Tkinter?

Análisis de código

Python
tamano = max(12, imagen.width // 20)

¿Qué tamaño de letra resulta para imágenes de 2000, 400 y 100 px de ancho? ¿Para qué sirve max?

Predicción

Una imagen de 1000 × 500 se procesa con thumbnail((500, 500)). ¿Qué tamaño queda? ¿Y con resize((500, 500))?

Depuración

"Mi marca debería verse semitransparente, pero se ve totalmente blanca y opaca." ¿Qué paso de la sección 3 falta probablemente?

Modificación

Cambia agregar_marca_texto para que reciba un parámetro esquina ("sup_izq", "sup_der", "inf_izq", "inf_der", "centro") y calcule la posición según él.

Creación

Escribe nombre_salida(ruta) que reciba "fotos/playa.png" y devuelva "fotos/playa_marca.png" (pista: pathlib.Path, atributos .stem y .suffix).


11. 🤖 Programar con apoyo de IA

Ciclo de trabajo: formula el problema → inténtalo tú primero → consulta a la IA sobre un punto concreto → lee y entiende → prueba → compara con la documentación oficial → modifica → explica con tus palabras.

Actividad 1 — Código desactualizado. Pide a una IA "cómo redimensionar una imagen con Pillow manteniendo la calidad". Si la respuesta usa ANTIALIAS o textsize, ejecútala, lee el error y corrígela con la documentación oficial de Pillow ("Deprecations and removals"). Anota qué versión de Pillow los eliminó.

Actividad 2 — Explicar para entender. Pide a una IA que explique Image.alpha_composite y luego comprueba su explicación con un experimento: compón una capa roja con alfa 0, 128 y 255 sobre una imagen azul y observa los resultados.

Actividad 3 — Revisar la interfaz. Describe tu ventana (sin pegar datos personales) y pide sugerencias de usabilidad. Aplica solo las que puedas justificar.

Declara el uso: sección "Uso de IA" en el README.md.


12. 🛠️ Observaciones sobre el material original

Archivo Observación Tratamiento
dia85-tarea4.md Menciona Pillow sin versión; muchos tutoriales en línea usan APIs eliminadas en Pillow 10 (ANTIALIAS, textsize) Se usa la API vigente y se advierte en errores frecuentes y en la actividad 1 de IA
dia85-tarea4.md El caso de uso (publicar fotos) no habla de derechos de autor ni de metadatos Sección 6
dia85-tarea4.md Remite a un servicio en línea (watermarkly.com) como referencia Se conserva como inspiración; no es necesario crear cuenta
dia85-tarea4.md "y algo de Google" Sección 3 y 4 explican los conceptos que habría que buscar

13. 📋 Matriz de trazabilidad

Contenido original Archivo de origen Concepto desarrollado Ejercicio original Reto adicional Proyecto relacionado
App de escritorio con Tkinter para cargar una imagen dia85-tarea4.md Sección 5 App de marca de agua Reto 3 (por lotes) Secciones 7 y 9
Agregar logo o texto como marca de agua con Python (Pillow) dia85-tarea4.md Secciones 3 y 4 App de marca de agua Retos 1, 2 y 4 Sección 7
Caso de uso: publicar fotos con tu sitio web dia85-tarea4.md Secciones 2 y 6 — — Sección 7 (contexto)
Recursos: Pillow, documentación de tkinter, Google dia85-tarea4.md Secciones 4, 5 y 11 — — —
Momento de reflexión dia85-tarea4.md Sección 7 (versión final) Pregunta de reflexión — Sección 9
(No existe en el curso original) — Derechos de autor, EXIF — Carnés para un evento Sección 8

14. 📦 Evidencias de aprendizaje del Día 85

  • La aplicación funcionando: capturas de la interfaz y de un antes/después.
  • La prueba automática de la lógica superada.
  • La tabla de pruebas de la sección 7 con resultados.
  • El DIARIO.md del Día 85, el repositorio y la ficha en el portafolio.
  • Cuaderno de errores: RGBA en JPEG, ANTIALIAS/textsize eliminados, fuente no encontrada, logo sin máscara, PhotoImage sin referencia, original sobrescrito, imagen deformada con resize.