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:
Leer un carácter
Si el carácter leído es un numeral: Descartar todos los caracteres que sigan hasta el
'n'
inclusive. Volver a 1.Si el carácter leído es un carácter blanco: Volver a 1.
Seguir leyendo caracteres hasta que venga un carácter blanco (o se termine la entrada). Almacenarlos.
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:
10
11
12
13
14
15
75029511
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
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.