Ejercicio obligatorio 2

Fecha de entrega: Domingo 1 de noviembre

Introducción

Netpbm

Desde el EJ1 que ya lo conocemos todo sobre el formato PGM... ponele. En este trabajo vamos a intentar operar sobre estas imágenes.

Si bien en la especificación de PGM se especifica que el valor máximo de cada pixel es es un número entre 1 y 65535 a partir de este momento tomaremos que el mismo está forzado en 255, lo cual es un valor bastante común para la representación de imágenes.

Volviendo sobre la estructura de los archivos PGM, ya sabemos que cada línea del mismo tiene que tener menos de 70 caracteres y siendo que los valores se separan por cualquier carácter blanco entonces la cantidad de valores por línea es un valor totalmente arbitrario.

Para complicar un poco más el formato de archivo, el mismo permite comentarios. Los comentarios van entre la aparición de cualquier carácter numeral ('#') y el final de la línea ('n') y si bien la especificación real es un poco más complicada asumamos que los comentarios no ocurren en el medio de otra cosa.

Entonces si bien escribir y entender un archivo PBM es algo bastante sencillo, leer un archivo es un poco más complejo.

Como ya sabemos de la materia, siempre que uno tiene que realizar una lectura lo primero que tiene que definir es la estrategia de si va a realizar la misma por caracteres o si la va a realizar por líneas. En este caso, dado que las líneas pueden tener una cantidad arbitraria de valores o pueden ser apenas un comentario es preferible leer de a caracteres por vez... o, leyendo caracteres de a uno por vez, combinarnos para obtener de a un valor numérico por vez.

Trabajo

Leer entero

Se pide implementar la función int leer_entero(); que lea de stdin el próximo valor numérico de un PGM y lo retorne. Si la función fallara por algún motivo debe devolver el valor -1 (un motivo de falla podría ser que se terminara la entrada en cualquier momento del proceso).

Todos los valores numéricos de un PGM están antecedidos por uno o más caracteres blancos y sucedidos por un carácter blanco. Ahora bien, antes del valor podría encontrarse un comentario, cuyo contenido tiene que ser ignorado.

Se propone el siguiente algoritmo para realizar la lectura:

  1. Leer un carácter

    1. Si el carácter leído es un numeral: Descartar todos los caracteres que sigan hasta el 'n' inclusive. Volver a 1.

    2. Si el carácter leído es un carácter blanco: Volver a 1.

  2. Seguir leyendo caracteres hasta que venga un carácter blanco (o se termine la entrada). Almacenarlos.

  3. Convertir esos caracteres almacenados en un valor entero. Devolverlo.

Por ejemplo, si se cargara el buffer de stdin con el siguiente contenido:

10
11 12
13
# Hola
14   15   # que
# tal
  # estas?
   75029511  0

y se llamara a la función leer_entero() repetidas veces, la misma debería devolver en cada una de sus invocaciones sucesivas:

  1. 10

  2. 11

  3. 12

  4. 13

  5. 14

  6. 15

  7. 75029511

  8. 0

Nota

Para saber si un carácter es blanco o no utilizar la función isspace() disponible en el encabezado <ctype.h>.

Imprimir PGM

Teniendo definidos:

#define MAX_ANCHO   1000
#define MAX_ALTO    1000

typedef unsigned char pixel_t;

se pide implementar la función void imprimir_pgm(pixel_t imagen[MAX_ALTO][MAX_ANCHO], size_t ancho, size_t alto); que reciba la matriz imagen que representa la imagen PGM de tamaño ancho por alto e imprima la misma por stdout.

Invertir valores

Implementar la función void invertir_valores(pixel_t imagen[MAX_ALTO][MAX_ANCHO], size_t ancho, size_t alto); que reciba una imagen PGM de ancho x alto y que invierta los valores de la misma. Invertir un valor es que donde había negro haya blanco y viceversa. Como cada pixel tiene valores entre \(0..255\) esto puede computarse como \(255 - v\) para cada valor \(v\).

Por ejemplo si se recibe la matriz:

0   255 10
25  100 125

se debe modificar a:

255 0   245
230 155 130

Espejar PGM

Implementar la función void espejar_horizontalmente(pixel_t imagen[MAX_ALTO][MAX_ANCHO], size_t ancho, size_t alto); que reciba una imagen PGM de ancho x alto y que espeje la matriz horizontalmente, es decir, que la voltee de izquierda a derecha.

Por ejemplo si se recibe la matriz:

0   255 10
25  100 125

se debe modificar a:

10  255 0
125 100 25

Aplicación

Desarrollar un programa que, haciendo uso de todas las funciones desarrolladas previamente lea una imagen desde stdin, la espeje horizontalmente, le invierta sus valores y la imprima por stdtout.

Validación

../_images/20202_ej2.png

Se proveen archivos PBM de ejemplo con sus respectivas salidas. El trabajo deberá contrastarse contra dichos ejemplos.

Los ejemplos se descargan de acá: archivos_20202_ej2.tar.gz

Entrega

Deberá entregarse el código fuente del programa desarrollado.

El programa debe compilar correctamente con los flags:

-Wall -Werror -std=c99 -pedantic

y validar los ejemplos dados.

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

El ejercicio es de entrega individual.