Ejercicio obligatorio 3
Fecha de entrega: Domingo 9 de octubre
Nota
Nunca es buena idea empezar por un ejercicio integrador antes de tener practicados los temas que el trabajo integra.
Se sugiere antes de desarrollar este trabajo resolver, al menos, los siguientes ejercicios de la guía de Memoria dinámica:
Ejercicio 12 (combinar vectores).
Ejercicio 14.a (matriz identidad).
Ejercicio 16 con el 1.b y 1.c de la guía de estructuras (dirección y persona).
Introducción
Queremos modelar una imagen, para ello definimos la estructura:
typedef struct {
pixel_t **pixeles;
size_t ancho, alto;
} imagen_t;
que permite almacenar en memoria una imagen según el siguiente esquema:
Trabajo
Creación y destrucción
Se pide implementar la función auxiliar
imagen_t *_imagen_crear(size_t ancho, size_t alto);
que genere la memoria necesaria para almacenar una imagen de ancho
x alto
píxeles. Los píxeles no deben ser inicializados. La función debe devolver la
imagen creada o NULL
en caso de falla.
Se pide implementar la función void imagen_destruir(imagen_t *imagen);
que libere la memoria asociada a la imagen
previamente creada.
Generación de imagen
Implementar una función
imagen_t *imagen_generar(size_t ancho, size_t alto, pixel_t valor);
que cree una imagen de ancho
x alto
con todos los pixeles inicializados en
valor
. La función debe retornar la imagen creada o NULL
en caso de
falla.
Lectura y escritura
Implementar la función imagen_t *imagen_leer_pgm();
que cargue una
imagen PGM desde stdin
y la devuelva. En caso de falla se debe devolver
NULL
.
Nota
Se puede asumir que la imagen tiene un formato como el siguiente:
P2
ancho alto
maximo
pixel1
pixel2
pixel3
...
es decir, luego del encabezado un pixel por línea.
La función debe validar que la primera línea sea exactamente "P2"
.
Implementar la función void imagen_imprimir_pgm(const imagen_t *imagen);
que imprima la imagen
por stdout
según el formato PGM. En esta función
asumir que el máximo vale 255.
Pegar y escalar
Implementar la función
void imagen_pegar(imagen_t *destino, const imagen_t *origen, int x, int y);
que pegue la imagen origen
en la imagen destino
, en las coordenadas
(x, y)
. Los píxeles de valor 0
son transparentes y no deben ser pegados.
Implementar una función
imagen_t *imagen_escalar(const imagen_t *origen, size_t ancho_destino, size_t alto_destino);
que devuelva una nueva imagen de tamaño ancho_destino
x alto_destino
en
base a escalar la imagen origen
. La función debe devolver NULL
en
caso de falla.
Aplicación y validación
Se provee el código fuente de la función main()
que realiza llamadas a cada
una de estas funciones. Dicha función debe ser la que se entregue como parte
del trabajo sin efectuarle modificaciones de ningún tipo
#include <stdint.h>
#include <assert.h>
typedef uint8_t pixel_t;
typedef struct {
pixel_t **pixeles;
size_t ancho, alto;
} imagen_t;
int main(void) {
imagen_t *imagen = imagen_generar(640, 480, 255);
assert(imagen != NULL);
imagen_t *squirtle = imagen_leer_pgm();
assert(squirtle != NULL);
imagen_t *squirtle_chico = imagen_escalar(squirtle, 208, 215);
assert(squirtle_chico != NULL);
imagen_t *squirtle_grande = imagen_escalar(squirtle, 834, 862);
assert(squirtle_grande != NULL);
imagen_pegar(imagen, squirtle, 10, 10);
imagen_pegar(imagen, squirtle_chico, 380, 20);
imagen_pegar(imagen, squirtle_grande, 280, 230);
assert(imagen_generar(1UL << 62, 10000, 0) == NULL);
imagen_imprimir_pgm(imagen);
imagen_destruir(imagen);
imagen_destruir(squirtle);
imagen_destruir(squirtle_chico);
imagen_destruir(squirtle_grande);
return 0;
}
Además se provee la siguiente imagen PGM
entrada_20222_ej3.pgm
El programa al ser invocado como:
./20222_ej3 < entrada_20222_ej3.pgm > salida_20222_ej3.pgm
deberá generar una imagen como la siguiente:
Entrega
Deberá entregarse el código fuente del programa desarrollado.
El programa debe:
Compilar correctamente con los flags:
-Wall -Werror -std=c99 -pedantic
pasar Valgrind correctamente,
validar la salida dada.
La entrega se realiza a través del sistema de entregas.
El ejercicio es de entrega individual.