Skip to content

Revisión automática de la práctica 03-imagen

Este es el resultado de una revisión automática de la prácica 03-imagen, tal y como la hemos recogido de este repositorio de entrega. Por favor, ten en cuenta que al ser una revisión automática, realizada en parte con la ayuda de un asistente de inteligencia artificial generativa, puede incluir errores, y ser incorrecta. Pero leela con atención, porque creemos que puede tener información útil. Si tienes cualquier duda, o crees que la revisión es errónea, por favor, consulta con los profesores de la asignatura.


Comprobación de archivos con extension '.py'

  • Archivos Python excluidos de la búsqueda: pixels.py, invert.py
  • Archivos Python encontrados (excluyendo esos): process.py

Correcto, se elige process.py como entrega.

Comprobación con ficheros de plantilla

Los archivos son diferentes de los de la plantilla.

Comprobación con ficheros de solución

Los archivos son diferentes de los de la solución.

Revisión automática de programa

Programa revisado:

#!/usr/bin/env python3
import sys
import pixels


def lee_argumentos() -> tuple[str, float, int]:
    """Lee los argumentos de la línea de comandos y devuelve el nombre del fichero, el factor de brillo y el desplazamiento."""
    if len(sys.argv) != 4:
        print("Uso: python3 process.py <fichero_imagen.gif> <factor_brillo (float)> <desplazamiento (int)>")
        sys.exit(1)

    imagen = sys.argv[1]
    try:
        brillo = float(sys.argv[2])
    except ValueError:
        print(f"Error: El factor de brillo debe ser un número real (float). Valor proporcionado: {sys.argv[2]}")
        sys.exit(1)

    try:
        desplazamiento = int(sys.argv[3])
    except ValueError:
        print(f"Error: El desplazamiento debe ser un número entero (int). Valor proporcionado: {sys.argv[3]}")
        sys.exit(1)

    return imagen, brillo, desplazamiento


# --------------------------------------------------

def _ajusta_componente(valor: float) -> int:
    """Función auxiliar para asegurar que el valor del componente RGB esté entre 0 y 255."""
    if valor > 255:
        return 255
    elif valor < 0:
        return 0
    return int(round(valor))


def cambia_brillo(brillo: float):
    """Aplica el factor de brillo a cada pixel de la imagen."""
    ancho, alto = pixels.tam_lienzo()
    for x in range(ancho):
        for y in range(alto):
            (r, g, b) = pixels.lee(x, y)

            r_nuevo = r * brillo
            g_nuevo = g * brillo
            b_nuevo = b * brillo

            r_final = _ajusta_componente(r_nuevo)
            g_final = _ajusta_componente(g_nuevo)
            b_final = _ajusta_componente(b_nuevo)

            pixels.pinta(x, y, (r_final, g_final, b_final))


# --------------------------------------------------

def cambia_desplazamiento(desplazamiento: int):
    """Aplica la variación de desplazamiento de los colores a cada pixel de la imagen."""
    ancho, alto = pixels.tam_lienzo()
    for x in range(ancho):
        for y in range(alto):
            (r, g, b) = pixels.lee(x, y)

            r_nuevo = r + desplazamiento
            g_nuevo = g + desplazamiento
            b_nuevo = b + desplazamiento

            r_final = _ajusta_componente(r_nuevo)
            g_final = _ajusta_componente(g_nuevo)
            b_final = _ajusta_componente(b_nuevo)

            pixels.pinta(x, y, (r_final, g_final, b_final))


# --------------------------------------------------

def main():
    imagen, brillo, desplazamiento = lee_argumentos()
    pixels.prepara(imagen)
    cambia_brillo(brillo)
    cambia_desplazamiento(desplazamiento)
    pixels.espera()


# --------------------------------------------------

if __name__ == "__main__":
    main()

Análisis

Cumple con el enunciado

El programa cumple con los requisitos técnicos del enunciado:

  • Lee correctamente los argumentos de la línea de comandos con lee_argumentos(), validando tipos y mostrando mensajes de error.
  • Aplica el cambio de brillo multiplicando cada componente RGB por el factor y ajustando valores fuera de rango con _ajusta_componente.
  • Aplica el desplazamiento sumando el mismo valor entero a los tres componentes RGB, también ajustando valores fuera de rango.
  • Sigue el orden de operaciones especificado: primero brillo, luego desplazamiento.
  • Incluye la estructura main() y el bloque if __name__ == "__main__".

Sin embargo, no sigue PEP8 en la separación de funciones: las líneas #-------------------------------------------------- son innecesarias y no cumplen con la recomendación de dejar dos líneas en blanco entre funciones de nivel superior.

Es fácil de leer y entender

El código es bastante claro para un principiante:

  • Usa nombres descriptivos en español (cambia_brillo, cambia_desplazamiento).
  • Incluye docstrings explicativos en cada función.
  • La lógica de procesamiento de píxeles está bien estructurada con bucles anidados.
  • La función auxiliar _ajusta_componente encapsula la lógica de ajuste de valores, evitando repetición de código.

Pero podría mejorar en:

  • Comentarios breves dentro de las funciones para explicar pasos clave (ej: "Aplicar factor de brillo a cada componente").
  • Explicar por qué se usa round() al convertir el brillo (aunque es correcto, no está explícito en la documentación).

Sigue buenas prácticas de programación

El programa aplica buenas prácticas:

  • Separa responsabilidades en funciones independientes.
  • Reutiliza la lógica de ajuste de valores con _ajusta_componente.
  • Valida tipos de datos y maneja errores de entrada.
  • Evita código duplicado en el procesamiento de píxeles.

Pero hay espacios de mejora:

  • La función _ajusta_componente podría simplificarse usando min(max(valor, 0), 255) en lugar de if-elif-else.
  • No se validan explícitamente que los valores de brillo y desplazamiento sean positivos o negativos (aunque el enunciado lo permite).

Recomendaciones de mejora

  1. Eliminar las líneas de separación con #-------------------------------------------------- y reemplazarlas por dos líneas en blanco entre funciones, como recomienda PEP8.
  2. Simplificar _ajusta_componente usando min(max(valor, 0), 255) para evitar condicionales múltiples.
  3. Agregar comentarios breves en las funciones cambia_brillo y cambia_desplazamiento explicando que el orden de aplicación (brillo primero, desplazamiento después) afecta el resultado final.
  4. Documentar el comportamiento de _ajusta_componente en su docstring, aclarando que acepta valores flotantes (por el brillo) y enteros (por el desplazamiento), ya que ambos fluyen a través de esta función.
  5. Validar que el factor de brillo sea positivo (aunque el enunciado no lo exige, un brillo negativo no tendría sentido lógico y podría causar errores en el procesamiento).