Added tolerance option and result example with -t 5

This commit is contained in:
Phuntsok Drak-pa 2018-11-27 23:59:04 +01:00
parent 88e04466f3
commit 2633662c4b
No known key found for this signature in database
GPG Key ID: 9CB34B6827C66D22
4 changed files with 55 additions and 19 deletions

BIN
img/asterix5p.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

View File

@ -5,19 +5,39 @@
#include "compress.h"
/**
* \var uint32_t tolerance
* \brief Color tolerance
*
* Cette variable est la valeur du pourcentage de tolérance couleur lors de la
* création de nouvelles zones. Cette variable contient une valeur située entre
* 0 et 100 inclus.
*/
int32_t tolerance;
/**
* Cette fonction permet dévaluer si le pixel passé en argument est éligible à
* la zone passée également en argument.
* la zone passée également en argument. Si la \ref tolerance a pour valeur 0,
* alors les couleurs doivent être strictements identiques. Sinon, leur
* différence doit être inférieure à la tolérance de couleur.
*
* \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, `1` si le pixel est éligible, `0` sinon
*/
int32_t sameColor(Pixel *t_pixel, Zone *t_zone) {
int diff_red, diff_green, diff_blue;
if (tolerance == 0) {
return (t_pixel->red == t_zone->red && t_pixel->green == t_zone->green &&
t_pixel->blue == t_zone->blue)
? 1
: 0;
}
diff_red = (abs((int32_t)t_zone->red - (int32_t)t_pixel->red) * 100) / 255;
diff_green =
(abs((int32_t)t_zone->green - (int32_t)t_pixel->green) * 100) / 255;
diff_blue = (abs((int32_t)t_zone->blue - (int32_t)t_pixel->blue) * 100) / 255;
return ((diff_red + diff_green + diff_blue) / 3) <= tolerance;
}
/**
@ -172,14 +192,17 @@ void write_compressed_file(Image *t_img, FILE *t_output, darray *t_zones) {
*
* \param[in] t_input_file Nom/chemin du fichier `.ppm` d'entrée
* \param[in] t_output_file Nom/chemin du fichier `.su` de sortie
* \param[in] t_tolerance Pourcentage de tolérance de couleur
*/
void compress(const char *t_input_file, const char *t_output_file) {
void compress(const char *t_input_file, const char *t_output_file,
int32_t t_tolerance) {
Image *img;
darray *zones;
FILE *output_file;
if (!t_output_file) {
t_output_file = DEFAULT_COMPRESSED_NAME;
}
tolerance = t_tolerance;
img = newImage();
imageLoadPPM(t_input_file, img);
output_file = get_file(t_output_file, "wb");

View File

@ -23,6 +23,7 @@ void write_segments(FILE *t_output, darray *t_segments);
/// Écrit les données compressées dans le fichier de sortie
void write_compressed_file(Image *t_img, FILE *t_output, darray *t_zones);
/// Compresse l'image d'entrée
void compress(const char *t_input_file, const char *t_output_file);
void compress(const char *t_input_file, const char *t_output_file,
int32_t tolerance);
#endif /* SRC_COMPRESS_H_ */

View File

@ -24,18 +24,21 @@
*/
void help(int t_exit_code) {
puts("Usage:\n"
"surfaces-unies -i path [-o path] [-options]\n\n"
"surfaces-unies -i path [-o path] [--options] [-t 0-100]\n\n"
"The default action is to compress the mandatory input image to a .su\n"
"file saved in the current directory.\n"
"The input image MUST be saved in the ppm format.\n"
"Options available:\n"
"-h --help\n\tdisplay the current message\n"
"-i --input\n\tpath to the input file (MANDATORY)\n"
"-h --help\n\tDisplay the current message\n"
"-i --input\n\tPath to the input file (MANDATORY)\n"
"-o --output\n"
"\tpath to the output file (if the file already exists, it will be\n"
"\tPath to the output file (if the file already exists, it will be\n"
"\toverwritten)\n"
"-c --compress\n\tcompress the input file\n"
"-u --uncompress\n\tuncompresses the input file to the output file.");
"-t --tolerance\n"
"\tColor tolerance for lossy compression. By default at 0 for lossless\n"
"\tcompression, at 100 will consider every color to be the same.\n"
"-c --compress\n\tCompress the input file\n"
"-u --uncompress\n\tUncompresses the input file to the output file.");
exit(t_exit_code);
}
@ -52,6 +55,7 @@ struct Argres {
char *input; /*!< Nom du fichier d'entrée */
char *output; /*!< Nom du fichier de sortie */
char compress; /*!< Le fichier d'entrée doit-il être compressé ? */
int32_t tolerance; /*!< Tolérance en pourcentage des différences de couleur */
};
typedef struct Argres Argres;
@ -72,6 +76,12 @@ void get_args(Argres *t_args, const int *const t_c) {
case 'o': (*t_args).output = optarg; break;
case 'c': (*t_args).compress = 1; break;
case 'u': (*t_args).compress = 0; break;
case 't':
(*t_args).tolerance = atoi(optarg);
if(t_args->tolerance < 0 || t_args->tolerance > 100) {
help(ARGERROR);
}
break;
case '?':
default: help(ARGERROR);
}
@ -95,16 +105,18 @@ Argres process_args(const int t_argc, char *t_argv[]) {
res.input = NULL;
res.compress = 1;
res.output = NULL;
res.tolerance = 0;
while (1) {
int option_index = 0;
static struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
{"input", required_argument, NULL, 'i'},
{"output", required_argument, NULL, 'o'},
{"tolerance", required_argument, NULL, 't'},
{"compress", no_argument, NULL, 'c'},
{"uncompress", no_argument, NULL, 'u'},
{NULL, 0, NULL, 0}};
int c = getopt_long(t_argc, t_argv, "hi:o:cu", long_options, &option_index);
int c = getopt_long(t_argc, t_argv, "hi:o:t:cu", long_options, &option_index);
if (c == -1)
break;
get_args(&res, &c);
@ -129,8 +141,8 @@ int main(int argc, char **argv) {
fprintf(stderr, "ERROR: no input file.");
help(ARGERROR);
}
if(argresults.compress) {
compress(argresults.input, argresults.output);
if (argresults.compress) {
compress(argresults.input, argresults.output, argresults.tolerance);
} else {
uncompress(argresults.input, argresults.output);
}