surfaces-unies/src/common.c
2018-11-12 14:25:24 +01:00

107 lines
3.4 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* \file common.c
* \brief Implémentation de la (dé)compression dimages
*/
#include "common.h"
/**
* Cette fonction permet dévaluer si le pixel passé en argument est éligible à
* la zone passée également en argument.
*
* \param[in] t_pixel Pointeur vers le pixel dont léligibilité est testée
* \param[in] t_zone Zone à laquelle le pixel est éligible ou non
* \return Valeur booléenne, `true` si le pixel est éligible, `false` sinon
*/
bool sameColor(Pixel_t t_pixel, Zone_t t_zone) {
return t_pixel->r == t_zone->r && t_pixel->g == t_zone->g &&
t_pixel->b == t_zone->b;
}
/**
* Ajoute un pixel à la zone passé en argument si le pixel à lindex passé en
* argument est éligible à la zone. Si un pixel na pas encore été visité, cela
* veut dire également quil ne fait partie daucun segment, il sera donc
* ajouté à un nouveau segment auquel seront rajoutés tous les pixels connexes
* éligibles à la zone. Ensuite, le segment est ajouté à la zone, et la
* fonction actuelle est appelée sur tous les pixels supérieurs et inférieurs
* aux pixels du segment.
*
* \param[in] t_img Image contenant les pixels explorés
* \param[in] t_idx Index du pixel actuel dans limage `t_img`
* \param[out] t_zone Zone à laquelle sera potentiellement ajouté le pixel
*/
void addPixelToSelectedZone(Image_t t_img, int t_idx, Zone_t t_zone) {
Pixel_t current_pixel;
int xd, xg, y = t_idx / (int)t_img->x;
current_pixel = darrayGet(t_img->pixels, t_idx);
if (current_pixel->visited || t_idx >= (int)darraySize(t_img->pixels) ||
t_idx < 0 || !sameColor(current_pixel, t_zone)) {
return;
}
(*current_pixel).visited = true;
for(xd = t_idx; xd % (int)t_img->x != 0; ++xd) { /* fetch right limit of segment */
current_pixel = darrayGet(t_img->pixels, xd);
if(!sameColor(current_pixel, t_zone)) {
break;
}
(*current_pixel).visited = true;
}
for(xg = t_idx; xg - y >= 0; --xg) { /* fetch right limit of segment */
current_pixel = darrayGet(t_img->pixels, xd);
if(!sameColor(current_pixel, t_zone)) {
break;
}
(*current_pixel).visited = true;
}
/* Add segment to its zone */
darrayPushBack(t_zone->segments, newSegment(y, xd, xg));
for(; xg <= xd; ++xg) { /* process every pixel up and down the segment */
addPixelToSelectedZone(t_img, t_idx + t_img->x, t_zone);
}
}
/* Selects the zone related to the pixel, skip tests if pixel has
already been visited */
void chooseZoneForPixel(Image_t t_img, int t_idx, darray_t zones) {
Zone_t current_zone;
Pixel_t pixel;
size_t i;
pixel = darrayGet(t_img->pixels, t_idx);
if (pixel->visited)
return;
for (i = 0; i < darraySize(zones); ++i) {
current_zone = darrayGet(zones, i);
if (sameColor(pixel, current_zone)) {
addPixelToSelectedZone(t_img, t_idx, current_zone);
break;
}
}
}
/* converts an image to zones */
darray_t imgToZones(Image_t t_img) {
darray_t zones;
const size_t nb_pixels = darraySize(t_img->pixels);
size_t i;
zones = darrayNew(sizeof(Zone));
for (i = 0; i < nb_pixels; ++i) {
chooseZoneForPixel(t_img, i, zones);
}
return zones;
}
void compress(const char *input_file) {
Image_t img;
darray_t zones;
img = newImage();
imageLoadPPM(input_file, img);
zones = imgToZones(img);
darrayDelete(zones);
printf("Detected %zu zones\n", darraySize(zones));
deleteImage(img);
}