From ef72f937b43108f79fa9b0b9ef8bcdd14685cdd9 Mon Sep 17 00:00:00 2001 From: Matteo Paonessa Date: Sun, 24 Apr 2016 11:00:44 +0200 Subject: [PATCH] Merge try 1 --- README.md | 8 ++- src/compresshelper.c | 150 +++++++++++++++++++++++++++++++++++++------ src/main.c | 78 ---------------------- 3 files changed, 137 insertions(+), 99 deletions(-) diff --git a/README.md b/README.md index 029e4c7..6967963 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ ## Caesium Command Line Tools -##### CCLT - v0.9.1-beta (build 20160223) - Copyright © Matteo Paonessa, 2016. All Rights Reserved. +##### CCLT - v0.9.1-beta (build 20160423) - Copyright © Matteo Paonessa, 2016. All Rights Reserved. ---------- @@ -11,7 +11,7 @@ ---------- ###### TESTED PLATFORMS -* Mac OS X El Capitan (v10.11.1) +* Mac OS X El Capitan (v10.11.4) * Arch Linux * Ubuntu 14.04.2 @@ -48,6 +48,7 @@ $ caesiumclt -l -R -o ~/output/ ~/Pictures ###### TODO * Code cleaning +* Keep folder structure ---------- @@ -64,7 +65,8 @@ Check the [Commits](https://github.com/Lymphatus/CaesiumCLT/commits/master) for ---------- ###### RESOURCES +* CaesiumCLT website - [http://saerasoft.com/caesium](http://saerasoft.com/caesium/clt) * Caesium website - [http://saerasoft.com/caesium](http://saerasoft.com/caesium) -* CCLT Git Repository - [https://github.com/Lymphatus/CaesiumCLT](https://github.com/Lymphatus/CaesiumCLT) +* CaesiumCLT Git Repository - [https://github.com/Lymphatus/CaesiumCLT](https://github.com/Lymphatus/CaesiumCLT) * Author website - SaeraSoft - [http://saerasoft.com](http://saerasoft.com) * Twitter - [Matteo Paonessa](https://twitter.com/MatteoPaonessa) diff --git a/src/compresshelper.c b/src/compresshelper.c index c0666f9..d9fb210 100644 --- a/src/compresshelper.c +++ b/src/compresshelper.c @@ -47,17 +47,51 @@ cclt_parameters initialize_compression_parameters() { return par; } -cclt_parameters parse_arguments(int argc, char* argv[]) { +void validate_parameters(cclt_compress_parameters* pars) { + //Either -l or -q must be set but not together + if (!((pars->lossless == 1) ^ (pars->quality > 0))) { + //Both or none are set + if (pars->lossless == 1 && pars->quality > 0) { + fprintf(stderr, "-l option can't be used with -q. Either use one or the other. Aborting.\n"); + exit(-1); + } else if (pars->lossless == 0 && pars->quality <= 0) { + fprintf(stderr, "Either -l or -q must be set. Aborting.\n"); + print_help(); + exit(-2); + } + } else { + //One of them is set + //If -q is set check it is within the 1-100 range + if (!(pars->quality >= 1 && pars->quality <= 100) && pars->lossless == 0) { + fprintf(stderr, "Quality must be within a [1-100] range. Aborting.\n"); + exit(-3); + } + } + + //Check if you set the input files + if (pars->input_files_count == 0) { + fprintf(stderr, "No input files. Aborting.\n"); + exit(-9); + } + + //Check if the output folder exists, otherwise create it + if (pars->output_folder == NULL) { + fprintf(stderr, "No -o option pointing to the destination folder. Aborting.\n"); + exit(-4); + } +} + +cclt_compress_parameters parse_arguments(int argc, char* argv[]) { //Initialize default params - cclt_parameters parameters = initialize_compression_parameters(); + cclt_compress_parameters parameters = initialize_compression_parameters(); int c; while (optind < argc) { if ((c = getopt (argc, argv, "q:velo:s:hR")) != -1) { switch (c) { case 'v': - printf("CaesiumCLT - Caesium Command Line Tools - Version %s (Build: %d)\n", APP_VERSION, BUILD); + printf("%s (Build: %d)\n", APP_VERSION, BUILD); exit(0); break; case '?': @@ -77,13 +111,13 @@ cclt_parameters parse_arguments(int argc, char* argv[]) { fprintf(stderr, "Parameter expected.\n"); break; case 'q': - parameters.jpeg.quality = string_to_int(optarg); + parameters.quality = string_to_int(optarg); break; case 'e': - parameters.jpeg.exif_copy = 1; + parameters.exif_copy = 1; break; case 'l': - parameters.jpeg.lossless = 1; + parameters.lossless = 1; break; case 'o': parameters.output_folder = optarg; @@ -112,7 +146,6 @@ cclt_parameters parse_arguments(int argc, char* argv[]) { printf("[WARNING] Folder found, skipping all other inputs.\n"); } scan_folder(¶meters, argv[optind], parameters.recursive); - //parameters.input_files = scan_folder(argv[optind], ¶meters.input_files_count, parameters.recursive); return parameters; } else { parameters.input_files[i] = (char*) malloc (strlen(argv[optind]) * sizeof(char)); //TODO Necessary?? @@ -125,25 +158,106 @@ cclt_parameters parse_arguments(int argc, char* argv[]) { } } + //Check if all parameters are poperly set + validate_parameters(¶meters); + return parameters; } -int cclt_compress_routine(char* input, char* output, cclt_parameters* pars) { +int cclt_compress_routine(char* input, char* output, cclt_compress_parameters* pars) { + //Detect which image type are we compressing enum image_type type = detect_image_type(input); - if (type == JPEG && pars->jpeg.lossless == 0) { - cclt_jpeg_compress(output, cclt_jpeg_decompress(input, &pars->jpeg), &pars->jpeg); - cclt_jpeg_optimize(output, output, pars->jpeg.exif_copy, input); - } else if (type == JPEG && pars->jpeg.lossless != 0) { - cclt_jpeg_optimize(input, output, pars->jpeg.exif_copy, input); - } else if (type == PNG) { - //Give a message to the user if he set a quality for PNGs - if (pars->jpeg.quality != 0) { - printf("PNG file, ignoring quality parameter.\n"); + + if (type == JPEG) { + //Lossy processing just uses the compression method before optimizing + if (!pars->lossless) { + cclt_jpeg_compress(output, cclt_jpeg_decompress(input, pars), pars); } - cclt_png_optimize(input, output, &pars->png); + //Optimize + cclt_jpeg_optimize(output, output, pars->exif_copy, input); + } else if (type == PNG) { + cclt_png_optimize(input, output); } else { printf("Unknown file type.\n"); return -1; } return 0; } + +void cclt_start(cclt_compress_parameters* pars, off_t* i_t_size, off_t* o_t_size) { + + struct stat st_buf; + int i = 0; + + //Creates the output folder (which will always be needed) + if (mkpath(pars->output_folder, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1) { + if (errno != EEXIST) { + fprintf(stderr, "Failed to create output directory. Aborting.\n"); + exit(-5); + } + } + + while (i < pars->input_files_count) { + + off_t i_size, o_size; + int status; //Pointer for stat() call + + char* output_filename = (char*) malloc ((strlen(pars->output_folder) + 1) * sizeof(char)); + + strcpy(output_filename, pars->output_folder); + + //Append / if was not entered by user + if (output_filename[strlen(pars->output_folder) - 1] != '/') { + strcat(output_filename, "/"); + } + + output_filename = realloc(output_filename, (strlen(output_filename) + strlen(basename(pars->input_files[i]))) * sizeof(char)); + output_filename = strcat(output_filename, basename(pars->input_files[i])); + + //Get input stats + status = stat(pars->input_files[i], &st_buf); + if (status != 0) { + fprintf(stderr, "Failed to get input file stats. Aborting.\n"); + exit(-11); + } + + //Check if we ran into a folder + //TODO Check symlinks too + if (is_directory(pars->input_files[i])) { + //Folder found, but we don't need it here + i++; + continue; + } + + //Get input file size + i_size = st_buf.st_size; + *(i_t_size) += i_size; + + //TODO Do we want a more verbose output? + fprintf(stdout, "Compressing: %s -> %s\n", pars->input_files[i], output_filename); + + int routine = cclt_compress_routine(pars->input_files[i], output_filename, pars); + if (routine == -1) { + i++; + continue; + } + + //Get output stats + status = stat(output_filename, &st_buf); + if (status != 0) { + //TODO This is not critical, but still something to be tracked + fprintf(stderr, "Failed to get output file stats. Aborting.\n"); + exit(-12); + } + o_size = st_buf.st_size; + *(o_t_size) += o_size; + + fprintf(stdout, "%s -> %s [%.2f%%]\n", + get_human_size(i_size), + get_human_size(o_size), + ((float) o_size - i_size) * 100 / i_size); + + i++; + } + +} diff --git a/src/main.c b/src/main.c index 81195df..ae2e8a0 100755 --- a/src/main.c +++ b/src/main.c @@ -28,84 +28,6 @@ //TODO If the output is INSIDE the folder we are passing as input, ignore it or we're gonna go in a infinite loop -void cclt_start(cclt_parameters* pars, off_t* i_t_size, off_t* o_t_size) { - - struct stat st_buf; - int i = 0; - - char** input_files = pars->input_files; - int n = pars->input_files_count; - char* output_folder = pars->output_folder; - - if (mkpath(output_folder, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1) { - if (errno != EEXIST) { - exit(-5); - } - } - - while (i < n) { - - off_t i_size, o_size; - int status; //Pointer for stat() call - - char* output_filename = (char*) malloc ((strlen(output_folder) + 1) * sizeof(char)); - - strcpy(output_filename, output_folder); - - //Append / if was not entered by user - if (output_filename[strlen(output_folder) - 1] != '/') { - strcat(output_filename, "/"); - } - - output_filename = realloc(output_filename, (strlen(output_filename) + strlen(basename(input_files[i]))) * sizeof(char)); - output_filename = strcat(output_filename, basename(input_files[i])); - - //Get input stats - status = stat(input_files[i], &st_buf); - if (status != 0) { - fprintf(stderr, "Failed to get input file stats. Aborting.\n"); - exit(-11); - } - - //Check if we ran into a folder - //TODO Check symlinks too - if (is_directory(input_files[i])) { - //Folder found, but we don't need it here - i++; - continue; - } - - //Get input file size - i_size = st_buf.st_size; - *(i_t_size) += i_size; - - //TODO Do we want a more verbose output? - fprintf(stdout, "Compressing: %s -> %s\n", input_files[i], output_filename); - - int routine = cclt_compress_routine(input_files[i], output_filename, pars); - if (routine == -1) { - i++; - continue; - } - - //Get output stats - status = stat(output_filename, &st_buf); - if (status != 0) { - //TODO This is not critical, but still something to be tracked - fprintf(stderr, "Failed to get output file stats. Aborting.\n"); - exit(-12); - } - o_size = st_buf.st_size; - *(o_t_size) += o_size; - - fprintf(stdout, "%s -> %s [%.2f%%]\n", - get_human_size(i_size), get_human_size(o_size), ((float) o_size - i_size) * 100 / i_size); - - i++; - } - -} - int main (int argc, char *argv[]) { errno = 0; off_t i_t_size = 0, o_t_size = 0;