Ejercicio obligatorio 2
Fecha de entrega: Lunes 19 de septiembre
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 Arreglos:
Ejercicio 3 (operaciones con vectores).
Ejercicio 9 (copia de vectores).
Ejercicio 18 (matrices) incisos d, e, h.
Ejercicio 19 (buscaminas).
Introducción
Imágenes
Ya sabemos todo lo que necesitamos saber sobre imágenes 🙄, sabemos que son discretizaciones en píxeles, conocemos el formato PGM, todo. Ahora lo que queremos es almacenar estas imágenes en la memoria. Para esto podemos usar matrices, que en principio es el tipo natural para modelar este problema.
Los píxeles en principio pueden representarse de múltiples maneras, para
abstraernos de eso en principio usaremos un tipo pixel_t
definido como:
typedef uint8_t pixel_t;
luego las imágenes serán matrices de una determinada cantidad de pixeles de
ancho por píxeles de alto, estando representado el ancho por sus columnas y el
alto por sus filas, siendo la fila 0
, la columna 0
el píxel de arriba a la
izquierda creciendo estos valores hacia abajo y hacia la derecha
respectivamente.
Dado que en el formato PGM el valor máximo de los píxeles es un valor
arbitrario de entre 1
y 65535
definiremos además un máximo para este
problema como:
#define PIXEL_MAXIMO 15
Escalado
En muchas aplicaciones es necesario cambiar las dimensiones de una imagen. Si bien hay muchas maneras de hacer esto, la forma más sencilla de hacerlo es sencillamente asignando a cada píxel de la nueva imagen valores de otro píxel de la imagen original.
Para simplificar el problema planteémoslo de forma unidimensional. Se tiene un vector original \(O\) de tamaño \(t_o\) y se quiere redimensionar a un nuevo vector destino \(D\) de tamaño \(t_d\). Es decir, hay que completar cada uno de los elementos \(D_i\) del vector \(D\) con elementos \(O_i\) provenientes de \(O\).
Si definimos:
\(e = \frac{t_o}{t_d},\)
como la escala, entonces podemos asignar cada elemento \(D_i\) según:
\(D_i = O_{\lfloor e \cdot i \rfloor},\)
con \(i \in [0, t_d)\), donde el operador \(\lfloor \cdots \rfloor\) es el operador "piso", es decir, el truncamiento entero.
Para escalar una imagen es el mismo procedimiento en dos dimensiones, admitiéndose diferentes escalas para el ancho y el alto.
Trabajo
Implementar una función
void inicializar_imagen(size_t ancho, size_t alto, pixel_t imagen[alto][ancho], pixel_t valor);
que reciba la matriz imagen
que representa una imagen de tamaño ancho
por alto
e incialice cada uno de los píxeles de la misma con el valor
dado.
Imprimir PGM
Se pide implementar la función
void imprimir_pgm(size_t ancho, size_t alto, pixel_t imagen[alto][ancho]);
que reciba una imagen
de ancho`x`alto
y la imprima por stdout
en formato
PGM.
Pegar imagen
Implementar una función
void pegar_imagen(
size_t ancho_destino, size_t alto_destino, pixel_t destino[alto_destino][ancho_destino],
size_t ancho_origen, size_t alto_origen, pixel_t origen[alto_origen][ancho_origen],
int x, int y
);`
que reciba dos imágenes, una imagen destino
de tamaño
ancho_destino`x`alto_destino
y una imagen origen
de tamaño
ancho_destino`x`alto_destino
y "pegue" la imagen origen
en la imagen
destino
de forma tal que la coordenada [0][0]
de origen
termine en la
posición [x][y]
de destino
(es decir, x
e y
representan dónde pegar la
esquina superior izquierda de destino
en origen
). Si el valor de un pixel
de origen
valiera 0
se debe considerar ese pixel como "transparente" y
NO debe ser pegado en la imagen.
Escalar imagen
Implementar una función
void escalar_imagen(
size_t ancho_destino, size_t alto_destino, pixel_t destino[alto_destino][ancho_destino],
size_t ancho_origen, size_t alto_origen, pixel_t origen[alto_origen][ancho_origen]
);`
que partiendo de la imagen origen
cree la imagen destino
escalándola
adecuadamente al tamaño de la misma.
Validación
Se provee el siguiente main()
#include <stdio.h>
#include <stdint.h>
#define MAXIMO 15
typedef uint8_t pixel_t;
#define ANCHO_IMAGEN 160
#define ALTO_IMAGEN 120
#define ANCHO_PEPE 46
#define ALTO_PEPE 38
pixel_t pepe[ALTO_PEPE][ANCHO_PEPE] = {
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 6, 6, 6, 6, 6, 6, 2, 3, 0, 0, 0, 0, 2, 2, 6, 6, 6, 2, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 0, 0, 3, 6, 6, 6, 6, 6, 6, 6, 6, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 1, 1, 6, 6, 6, 6, 6, 1, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 6, 6, 3, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 6, 8, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 1, 6, 3, 0, 0},
{0, 0, 0, 0, 0, 0, 2, 2, 6, 6, 6, 9, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 6, 2, 0},
{0, 0, 0, 0, 0, 3, 6, 6, 6, 6, 6, 9, 6, 6, 6, 6, 6, 6, 6, 2, 3, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, 2, 2, 0},
{0, 0, 0, 0, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 3, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 3, 0},
{0, 0, 0, 0, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 12, 12, 12, 12, 12, 12, 2, 2, 12, 12, 12, 12, 12, 3, 12, 13, 13, 13, 13, 13, 12, 2, 2, 12, 13, 13, 12, 12, 3},
{0, 0, 0, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 12, 12, 12, 12, 12, 12, 2, 2, 12, 12, 12, 12, 12, 2, 12, 13, 13, 13, 13, 13, 12, 2, 2, 12, 13, 13, 12, 12, 3},
{0, 0, 0, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 3, 12, 13, 13, 13, 13, 13, 13, 12, 12, 13, 13, 13, 12, 4, 0},
{0, 0, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 3, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 4, 0, 0},
{0, 0, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2, 12, 12, 12, 12, 12, 12, 12, 12, 1, 2, 2, 2, 12, 12, 12, 12, 12, 12, 12, 2, 2, 3, 0, 0, 0},
{0, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 1, 1, 1, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 5, 2, 0, 0, 0, 0},
{0, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 1, 6, 6, 1, 6, 6, 6, 6, 6, 6, 6, 5, 3, 0, 0, 0, 0, 0},
{2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 1, 6, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0},
{2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 6, 6, 6, 6, 6, 6, 6, 1, 1, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 0, 0, 0, 0, 0},
{2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 9, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 0, 0, 0, 0},
{2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 9, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 0, 0, 0, 0},
{2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 9, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 0, 0, 0},
{2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 0, 0, 0},
{2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 2, 0, 0, 0},
{2, 6, 6, 6, 8, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 1, 1, 7, 7, 3, 0, 0},
{0, 2, 6, 6, 9, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 6, 6, 6, 6, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 7, 7, 7, 3, 0, 0},
{0, 2, 6, 6, 9, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 7, 1, 1, 1, 1, 1, 1, 1, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 1, 1, 1, 3, 0, 0, 0},
{0, 0, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 6, 7, 7, 7, 7, 7, 7, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 2, 0, 0, 0, 0},
{0, 0, 0, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 0, 0, 0, 0},
{0, 0, 0, 0, 2, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 2, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
int main(void) {
pixel_t imagen[ALTO_IMAGEN][ANCHO_IMAGEN];
inicializar_imagen(ANCHO_IMAGEN, ALTO_IMAGEN, imagen, MAXIMO);
pegar_imagen(ANCHO_IMAGEN, ALTO_IMAGEN, imagen, ANCHO_PEPE, ALTO_PEPE, pepe, 60, 40);
pegar_imagen(ANCHO_IMAGEN, ALTO_IMAGEN, imagen, ANCHO_PEPE, ALTO_PEPE, pepe, 140, 40);
pegar_imagen(ANCHO_IMAGEN, ALTO_IMAGEN, imagen, ANCHO_PEPE, ALTO_PEPE, pepe, -20, 40);
pegar_imagen(ANCHO_IMAGEN, ALTO_IMAGEN, imagen, ANCHO_PEPE, ALTO_PEPE, pepe, 60, 100);
pegar_imagen(ANCHO_IMAGEN, ALTO_IMAGEN, imagen, ANCHO_PEPE, ALTO_PEPE, pepe, 60, -20);
pixel_t escalada1[19][23];
escalar_imagen(23, 19, escalada1, ANCHO_PEPE, ALTO_PEPE, pepe);
pegar_imagen(ANCHO_IMAGEN, ALTO_IMAGEN, imagen, 23, 19, escalada1, 10, 10);
pixel_t escalada2[60][60];
escalar_imagen(60, 60, escalada2, ANCHO_PEPE, ALTO_PEPE, pepe);
pegar_imagen(ANCHO_IMAGEN, ALTO_IMAGEN, imagen, 60, 60, escalada2, 100, 80);
imprimir_pgm(ANCHO_IMAGEN, ALTO_IMAGEN, imagen);
return 0;
}
el cual debe generar la siguiente imagen:

Probar las funciones realizadas contra esta referencia.
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 la salida esperada sin errores.
La entrega se realiza a través del sistema de entregas.
El ejercicio es de entrega individual.