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:

import sys
import pixels


def lee_argumentos() -> tuple[str, float, int]:
    if len(sys.argv) != 4:
        print(f"Uso: python3 {sys.argv[0]} <imagen.gif> <brillo> <desplazamiento>",
              file=sys.stderr)
        sys.exit(1)

    try:
        imagen = sys.argv[1]
        brillo = float(sys.argv[2])
        desplazamiento = int(sys.argv[3])
    except ValueError:
        print("Error: El brillo debe ser un número real (float) "
              "y el desplazamiento un número entero (int).", file=sys.stderr)
        sys.exit(1)

    return imagen, brillo, desplazamiento


def _clamp_color(valor: int) -> int:
    return min(255, max(0, valor))


def cambia_brillo(brillo: float):
    ancho = pixels.get_width()
    alto = pixels.get_height()

    for y in range(alto):
        for x in range(ancho):
            r, g, b = pixels.get_color(x, y)
            nuevo_r = int(r * brillo)
            nuevo_g = int(g * brillo)
            nuevo_b = int(b * brillo)
            pixels.set_color(x, y, (
                _clamp_color(nuevo_r),
                _clamp_color(nuevo_g),
                _clamp_color(nuevo_b)
            ))


def cambia_desplazamiento(desplazamiento: int):
    ancho = pixels.get_width()
    alto = pixels.get_height()

    for y in range(alto):
        for x in range(ancho):
            r, g, b = pixels.get_color(x, y)
            nuevo_r = r + desplazamiento
            nuevo_g = g + desplazamiento
            nuevo_b = b + desplazamiento
            pixels.set_color(x, y, (
                _clamp_color(nuevo_r),
                _clamp_color(nuevo_g),
                _clamp_color(nuevo_b)
            ))


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 todos los requisitos especificados:

  • Lee correctamente los tres argumentos de línea de comandos (imagen, brillo y desplazamiento)
  • Aplica el cambio de brillo multiplicando cada componente RGB por el factor y limitando valores entre 0-255
  • Aplica el desplazamiento sumando el mismo valor entero a cada componente RGB y limitando valores entre 0-255
  • Tiene la estructura de main() exactamente como se especifica en el enunciado
  • Incluye la protección if __name__ == "__main__" para ejecución independiente

Es fácil de leer y entender

El código es comprensible para estudiantes principiantes:

  • Usa funciones bien separadas con nombres claros en español
  • Incluye un helper _clamp_color que encapsula la lógica de limitación de valores
  • Tiene una estructura lógica de procesamiento: lectura de argumentos → preparar imagen → aplicar brillo → aplicar desplazamiento → esperar
  • Utiliza variables con nombres significativos (r, g, b para componentes RGB)

Sigue buenas prácticas de programación

⚠️ El código sigue buenas prácticas básicas, pero hay algunos puntos de mejora:

  • Usa funciones para separar responsabilidades
  • Incluye manejo de errores para argumentos inválidos
  • El helper _clamp_color evita repetición de código
  • No hay comentarios ni docstrings que expliquen el propósito de cada función
  • La línea de error en lee_argumentos supera los 79 caracteres recomendados por PEP8

Recomendaciones de mejora

  1. Añadir docstrings a todas las funciones
    Ejemplo para cambia_brillo:

    def cambia_brillo(brillo: float):
        """Modifica cada pixel multiplicando sus componentes RGB por el factor de brillo.
        Los valores resultantes se limitan entre 0 y 255."""
  2. Mejorar formato PEP8 en líneas largas
    Reformatear el mensaje de error para que no supere los 79 caracteres:

    print("Error: El brillo debe ser un número real (float) "
          "y el desplazamiento un número entero (int).", 
          file=sys.stderr)
  3. Considerar redondeo en cambio de brillo
    Actualmente se trunca el valor al convertir a int. Para brillo, podría ser más preciso:

    nuevo_r = int(round(r * brillo))
  4. Optimizar bucles con range directo
    En vez de:

    ancho = pixels.get_width()
    alto = pixels.get_height()
    for y in range(alto):
        for x in range(ancho):

    Podría simplificarse a:

    for y in range(pixels.get_height()):
        for x in range(pixels.get_width()):
  5. Evitar procesamiento redundante
    Actualmente se recorre toda la imagen dos veces (una para brillo y otra para desplazamiento). Para optimizar:

    def procesa_imagen(brillo: float, desplazamiento: int):
        """Aplica brillo y desplazamiento en un solo recorrido de la imagen"""
        for y in range(pixels.get_height()):
            for x in range(pixels.get_width()):
                r, g, b = pixels.get_color(x, y)
                # Aplicar ambos efectos en un solo paso
                nuevo_r = _clamp_color(int(r * brillo) + desplazamiento)
                # ...similar para g y b...
                pixels.set_color(x, y, (nuevo_r, nuevo_g, nuevo_b))
  6. Añadir validación de rango para desplazamiento
    Aunque el enunciado permite cualquier entero, podría mejorar con:

    if not (-255 <= desplazamiento <= 255):
        print("Advertencia: El desplazamiento podría causar saturación de colores", 
              file=sys.stderr)
  7. Considerar manejo de tipos en parámetros
    Aunque el enunciado no lo requiere, podría verificar que el archivo tenga extensión .gif:

    if not imagen.lower().endswith('.gif'):
        print("Error: El archivo debe ser de tipo GIF", file=sys.stderr)
        sys.exit(1)