Trabajo Práctico 1

Fecha de entrega: Domingo 7 de marzo

Introducción

Objetivo

El objetivo del presente trabajo práctico es la implementación de un software de terminal para el procesamiento de imágenes.

El trabajo consiste en la resolución de un problema mediante el diseño y uso de TDAs y en la reutilización de los tipos desarrollados a lo largo del curso en trabajos anteriores.

Alcances

Mediante el presente TP se busca que el estudiante adquiera y aplique conocimientos sobre los siguientes temas:

  • Encapsulamiento en TDAs,

  • Punteros a funciones,

  • Archivos,

  • CLA,

  • Modularización,

  • Técnicas de abstracción,

además de los temas ya evaluados en trabajos anteriores.

Trabajo

El enunciado de este trabajo será breve, no se introducirá ningún concepto nuevo. Ya tenemos implementado nuestro TDA pixel_t, imagen_t, ya conocemos los formatos PPM y BMP, ya resolvimos problemas donde nos pidieron implementar funciones y módulos con interfases ya previamente diseñadas. También tenemos como ejemplos los códigos de prueba dados.

En este trabajo se planteará un problema, y el alumno deberá resolverlo con las herramientas ya adquiridas, deberá extender de forma consistente los TDAs y módulos ya desarrollados y deberá diseñar los TDAs que el problema requiera. Se evaluará además el correcto uso de los TDAs respetando la abstracción y el "modelo" de Alan-Bárbara.

Requerimientos

Se quiere tener una aplicación que pueda realizar transformaciones arbitrarias de archivos PPM y BMP. Por ejemplo, si se ejecutara:

$ ./20202_tp1 -input gatito.bmp -filter brillo -20 -filter sepia -output gatito_oscuro_sepia.bmp

el programa deberá abrir como entrada (-input) el archivo gatito.bmp y deberá aplicar en ese orden los filtros (-filter) de brillo con parámetro -20 y luego el filtro sepia, el resultado de las operaciones se guardará (-output) como el archivo gatito_oscuro_sepia.bmp.

En todas las operaciones hay involucrado un archivo de entrada y un archivo de salida, que a su vez puede ser BMP o PPM. La extensión del archivo determinará si se trata de uno o del otro. Además puede no especificarse la entrada o no especificarse la salida, en esos casos se asumirá que se lee un PPM por stdin o que se escribe un PPM por stdout respectivamente.

El orden de los parámetros no importa, más allá del orden relativo de los filtros que deben ser aplicados en la secuencia que se defina. Es decir, si bien siempre después de -input debe estar el nombre del archivo de entrada, nadie dice que -input (de venir) tenga que estar en argv[1], el par -input + nombredearchivo puede estar en cualquier ubicación.

La aplicación permitirá aplicar los filtros (-filter) del EJ4 pero también las operaciones de recorte (-crop) del EJ3 y de espejado horizontal (-horizontal) del EJ2.

A continuación todas las opciones del programa:

Flag

Significado

Parámetros

Ejemplos

-input

Archivo de entrada

1: Nombre de archivo

-input gatito.bmp

-output

Archivo de salida

1: Nombre de archivo

-output gatito.ppm

-filter

Filtro

2 o 3: Nombre de filtro y parámetros

-filter sepia, -filter gama 100

-crop

Recorte

1: Área de recorte (ver después)

-crop 100x150+20+30`

-horizontal

Espejado horizontal

0

-horizontal

-vertical

Espejado vertical

0

-vertical

Los parámetros de recorte son WxH+X+Y donde W es ancho, H alto, X el x0 e Y el y0 (ver imagen_recortar del EJ3). En el ejemplo de la tabla se recorta un recuadro de 100x150 pixeles partiendo del \((20, 30)\).

Algunos ejemplos de invocación:

Lee un PPM de stdin, le aplica el filtro valencia y lo vuelca como PPM en stdout:

$ ./20202_tp1 -filter valencia < gatito.ppm > gatito_valencia.ppm

Lee como entrada el BMP gatito.bmp, lo espeja horizontalmente, recorta un área de 100x100 pixeles en la esquina superior izquierda, lo espeja de vuelta, lo guarda como un PPM gatito.ppm. El resultado de la serie de operaciones es una imagen de 100x100 equivalente a haber recortado la esquina superior derecha de la imagen original.:

$ ./20202_tp1 -input gatito.bmp -horizontal -crop 100x100+0+0 -horizontal -output gatito.ppm

Lee como entrada el PPM gatito.ppm, le aplica una mezcla con el color magenta (0xFF00FF), invierte los colores, le aplica el filtro toaster y lo guarda como el BMP gatito.bmp:

$ ./20202tp1 -filter mezclar magenta -filter invertir -output gatito.bmp -input gatito.ppm -filter toaster

Lee como entrada un PPM de stdin y lo escribe como PPM por stdout:

$ ./20202tp1

Algunos ejemplos (no extensivos) de invocación incorrecta:

Opción inválida:

$ ./20202tp1 -banana

$ ./20202tp1 banana

Falta nombre de archivo:

$ ./20202tp1 -input

Filtro inválido:

$ ./20202tp1 -filter difuminado

Parámetros incorrectos en el filtro:

$ ./20202tp1 -filter monocromo

Esto no va:

Color inexistente $ ./20202tp1 -filter mezclar mostaza

Parámetros inválidos de recorte:

$ ./20202tp1 -crop 6x6+8

Nota

Se incluyen estos ejemplos para dar un panorama de qué cosas hay que mirar, hay otras invocaciones inválidas no incluídas acá.

Nota

Si bien tanto -input como -output deberían ser únicos, no hace falta que se considere como error la repetición. Bien puede optarse por quedarse con la primera, la última o alguna de las ocurrencias. Tampoco estaría mal si se considerara como un error. Se deja a criterio del alumno.

Diseño

En cualquier aplicación se distinguen tres etapas bien definidas:

  1. Entrada y validación

  2. Procesamiento

  3. Salida

Debe respetarse este esquema. Es decir, el procesamiento de todos los argumentos debe hacerse en la etapa 1. ¿Qué significa procesar?, procesar significa convertir todas esas cadenas de caracteres a entidades que tengan sentido dentro de la aplicación, como enumerativos, punteros, punteros a funciones, instancias de TDAs, y al realizar ese procesamiento además deben validarse. Dicho por la negativa, si al momento de hacer una mezcla se tiene todavía una cadena que diga "magenta" y no un pixel_t con la representación de ese color (o en su defecto el entero 0xFF00FF) o si todavía se tiene la cadena "mezclar" y no un puntero a función a filtro_mezclar (o en su defecto a algún enumerativo que identifique esta función) el trabajo práctico está mal.

El trabajo práctico es de TDAs. Debe implementarse un TDA para resolver la funcionalidad de procesamiento de argumentos. El paso de entrada en algún momento generará un vector de operaciones que se aplicarán en el procesamiento. Ese vector deberá ser también un TDA. El no uso de TDAs para resolver estos problemas implicará que el trabajo práctico esté mal.

Nota

El procesamiento de los argumentos de este trabajo es complejo. Es imprescindible que las estructuras y estrategias que se van a implementar se diseñen y prueben primero. Cualquier estrategia de empezar a programar sobre la marcha e ir viendo va a fracasar.

Entrega

Requisitos

Los únicos requisitos son que el programa resuelva correctamente la funcionalidad pedida y que lo haga utilizando TDAs con un diseño planificado a conciencia. Si hacés eso nada puede salir mal.

Entregables

Deberá entregarse:

  1. El código fuente del trabajo debidamente documentado.

  2. El archivo Makefile para compilar el proyecto.

Nota

El programa debe:

  • estar programado en C,

  • estar completo,

  • compilar...

  • sin errores...

  • sin warnings,

  • correr...

  • sin romperse...

  • sin fugar memoria...

  • resolviendo el problema pedido...

  • esto es generando un BMP/PPM válido a un BMP/PPM de entrada.

Trabajos que no cumplan con lo anterior no serán corregidos.

La entrega se realiza a través del sistema de entregas.

El ejercicio es grupal permitiéndose grupos de hasta 2 integrantes.

Si elegís hacer el trabajo en grupo te pedimos que nos avises o por mail o por Discord quién es tu compañero de grupo así lo cargamos en el sistema de entregas. (Si el grupo sufriera alteraciones avisanos también.)