Added tolerance option and result example with -t 5
This commit is contained in:
		
							parent
							
								
									88e04466f3
								
							
						
					
					
						commit
						2633662c4b
					
				
							
								
								
									
										
											BIN
										
									
								
								img/asterix5p.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								img/asterix5p.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 51 KiB  | 
@ -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) {
 | 
			
		||||
  return (t_pixel->red == t_zone->red && t_pixel->green == t_zone->green &&
 | 
			
		||||
          t_pixel->blue == t_zone->blue)
 | 
			
		||||
             ? 1
 | 
			
		||||
             : 0;
 | 
			
		||||
  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");
 | 
			
		||||
 | 
			
		||||
@ -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_ */
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										36
									
								
								src/main.c
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								src/main.c
									
									
									
									
									
								
							@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -49,9 +52,10 @@ void help(int t_exit_code) {
 | 
			
		||||
 *  supplémentaires aux fonctions.
 | 
			
		||||
 */
 | 
			
		||||
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é ? */
 | 
			
		||||
  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);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user