Solved output file string issues
This commit is contained in:
parent
0300036b4c
commit
5e1d546c9d
|
@ -1,4 +1,15 @@
|
|||
cmake_minimum_required(VERSION 2.8.11)
|
||||
project(caesium_clt)
|
||||
|
||||
# The version number.
|
||||
set(VERSION_MAJOR 0)
|
||||
set(VERSION_MINOR 10)
|
||||
set(VERSION_PATCH 0)
|
||||
|
||||
configure_file(
|
||||
"src/config.h.in"
|
||||
"${PROJECT_BINARY_DIR}/config.h"
|
||||
)
|
||||
|
||||
include_directories("${PROJECT_BINARY_DIR}")
|
||||
add_subdirectory(src)
|
20
README.md
20
README.md
|
@ -1,17 +1,19 @@
|
|||
## Caesium Command Line Tools
|
||||
##### CCLT - v0.9.1-beta (build 20160808) - Copyright © Matteo Paonessa, 2016. All Rights Reserved.
|
||||
## Caesium CommandLineTools
|
||||
##### caesium-clt - v0.10.0-beta (build 20161219) - Copyright © Matteo Paonessa, 2016. All Rights Reserved.
|
||||
|
||||
----------
|
||||
|
||||
###### REQUIREMENTS
|
||||
* [mozjpeg](https://github.com/mozilla/mozjpeg)
|
||||
* [zopflipng](https://github.com/google/zopfli)
|
||||
* [lodepng](https://github.com/lvandeve/lodepng)
|
||||
* [libcaesium](https://github.com/mozilla/mozjpeg)
|
||||
|
||||
###### Included libraries
|
||||
* [optparse](https://github.com/skeeto/optparse)
|
||||
* [tinydir](https://github.com/cxong/tinydir)
|
||||
|
||||
----------
|
||||
|
||||
###### TESTED PLATFORMS
|
||||
* Mac OS X El Capitan (v10.11.4)
|
||||
* Mac OS X Sierra (v10.12.1)
|
||||
* Arch Linux
|
||||
|
||||
----------
|
||||
|
@ -60,13 +62,13 @@ $ caesiumclt -q 0 -R -o ~/output/ ~/Pictures
|
|||
* 0.10.0-beta - Switched to cmake and libcaesium
|
||||
* 0.9.1-beta - Initial development stage
|
||||
|
||||
Check the [Commits](https://github.com/Lymphatus/CaesiumCLT/commits/master) for a detailed list of changes.
|
||||
Check the [Commits](https://github.com/Lymphatus/caesium-clt/commits/master) for a detailed list of changes.
|
||||
|
||||
----------
|
||||
|
||||
###### RESOURCES
|
||||
* CaesiumCLT website - [http://saerasoft.com/caesium/clt](http://saerasoft.com/caesium/clt)
|
||||
* caesium-clt website - [http://saerasoft.com/caesium/clt](http://saerasoft.com/caesium/clt)
|
||||
* Caesium website - [http://saerasoft.com/caesium](http://saerasoft.com/caesium)
|
||||
* CaesiumCLT Git Repository - [https://github.com/Lymphatus/CaesiumCLT](https://github.com/Lymphatus/CaesiumCLT)
|
||||
* caesium-clt Git Repository - [https://github.com/Lymphatus/CaesiumCLT](https://github.com/Lymphatus/caesium-clt)
|
||||
* Author website - SaeraSoft - [http://saerasoft.com](http://saerasoft.com)
|
||||
* Twitter - [Matteo Paonessa](https://twitter.com/MatteoPaonessa)
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
#define VERSION_MAJOR @VERSION_MAJOR@
|
||||
#define VERSION_MINOR @VERSION_MINOR@
|
||||
#define VERSION_PATCH @VERSION_PATCH@
|
||||
|
60
src/helper.c
60
src/helper.c
|
@ -4,6 +4,7 @@
|
|||
#include "helper.h"
|
||||
#include "optparse.h"
|
||||
#include "utils.h"
|
||||
#include "config.h"
|
||||
|
||||
void initialize_jpeg_parameters(cs_image_pars *options)
|
||||
{
|
||||
|
@ -38,7 +39,7 @@ cclt_options parse_arguments(char **argv, cs_image_pars *options)
|
|||
{
|
||||
struct optparse opts;
|
||||
//Initialize application options
|
||||
cclt_options result = {NULL, NULL, false, false, 0};
|
||||
cclt_options result = {NULL, NULL, false, false, 0, 0, 0};
|
||||
|
||||
//Parse command line args
|
||||
optparse_init(&opts, argv);
|
||||
|
@ -58,13 +59,22 @@ cclt_options parse_arguments(char **argv, cs_image_pars *options)
|
|||
switch (option) {
|
||||
case 'q':
|
||||
options->jpeg.quality = atoi(opts.optarg);
|
||||
if (options->jpeg.quality < 0 || options->jpeg.quality > 100) {
|
||||
//TODO Trigger a error
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
case 'e':
|
||||
options->jpeg.exif_copy = true;
|
||||
break;
|
||||
case 'o':
|
||||
if (opts.optarg[strlen(opts.optarg) - 1] == '/') {
|
||||
result.output_folder = malloc((strlen(opts.optarg) + 1) * sizeof(char));
|
||||
strncpy(result.output_folder, opts.optarg, strlen(opts.optarg) + 1);
|
||||
snprintf(result.output_folder, strlen(opts.optarg) + 1, "%s", opts.optarg);
|
||||
} else {
|
||||
result.output_folder = malloc((strlen(opts.optarg) + 2) * sizeof(char));
|
||||
snprintf(result.output_folder, strlen(opts.optarg) + 2, "%s/", opts.optarg);
|
||||
}
|
||||
break;
|
||||
case 'R':
|
||||
result.recursive = true;
|
||||
|
@ -73,7 +83,7 @@ cclt_options parse_arguments(char **argv, cs_image_pars *options)
|
|||
result.keep_structure = true;
|
||||
break;
|
||||
case 'v':
|
||||
fprintf(stdout, "%s-%d\n", APP_VERSION_STRING, BUILD);
|
||||
fprintf(stdout, "%d.%d.%d\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH);
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'h':
|
||||
print_help();
|
||||
|
@ -89,11 +99,8 @@ cclt_options parse_arguments(char **argv, cs_image_pars *options)
|
|||
char *arg;
|
||||
bool files_flag = false, folders_flag = false;
|
||||
while ((arg = optparse_arg(&opts))) {
|
||||
//TODO Check if there's a folder and change behaviour accordingly
|
||||
//Check if it's a directory and add its content
|
||||
if (is_directory(arg)) {
|
||||
//NOTE Scanning a folder with this function does not check if we are actually getting images
|
||||
//The actual check is performed by the library
|
||||
int count = 0;
|
||||
count = scan_folder(arg, &result, result.recursive);
|
||||
if (count == 0) {
|
||||
|
@ -101,10 +108,9 @@ cclt_options parse_arguments(char **argv, cs_image_pars *options)
|
|||
}
|
||||
|
||||
} else {
|
||||
result.input_files = realloc(result.input_files, (result.files_count + 1) * sizeof(char*));
|
||||
result.input_files = realloc(result.input_files, (result.files_count + 1) * sizeof(char *));
|
||||
result.input_files[result.files_count] = malloc((strlen(arg) + 1) * sizeof(char));
|
||||
//TODO Replace with strdup for alloc
|
||||
strncpy(result.input_files[result.files_count], arg, strlen(opts.optarg) + 1);
|
||||
snprintf(result.input_files[result.files_count], strlen(arg) + 1, "%s", arg);
|
||||
result.files_count++;
|
||||
}
|
||||
}
|
||||
|
@ -118,8 +124,10 @@ cclt_options parse_arguments(char **argv, cs_image_pars *options)
|
|||
|
||||
int start_compression(cclt_options *options, cs_image_pars *parameters)
|
||||
{
|
||||
int compressed_files = 0;
|
||||
off_t input_file_size = 0;
|
||||
off_t output_file_size = 0;
|
||||
//TODO Support folder structure
|
||||
int status = 0;
|
||||
|
||||
//Create the output folder if does not exists
|
||||
if (mkpath(options->output_folder, 0777) == -1) {
|
||||
|
@ -128,21 +136,35 @@ int start_compression(cclt_options *options, cs_image_pars *parameters)
|
|||
}
|
||||
|
||||
for (int i = 0; i < options->files_count; i++) {
|
||||
//TODO remove unnecessary "/"s
|
||||
char *filename = get_filename(options->input_files[i]);
|
||||
char *output_full_path = malloc((strlen(filename) + strlen(options->output_folder) + 2) * sizeof(char));
|
||||
strncpy(output_full_path, options->output_folder, strlen(options->output_folder));
|
||||
strcat(output_full_path, "/");
|
||||
strcat(output_full_path, filename);
|
||||
char *output_full_path = malloc((strlen(filename) + strlen(options->output_folder) + 1) * sizeof(char));
|
||||
snprintf(output_full_path, (strlen(filename) + strlen(options->output_folder) + 1), "%s%s", options->output_folder, filename);
|
||||
|
||||
fprintf(stdout, "(%d/%d) %s -> %s\n",
|
||||
i + 1,
|
||||
options->files_count,
|
||||
filename,
|
||||
output_full_path);
|
||||
|
||||
fprintf(stdout,
|
||||
"Compressing %s in %s\n", filename, output_full_path);
|
||||
cs_compress(options->input_files[i], output_full_path, parameters);
|
||||
input_file_size = get_file_size(options->input_files[i]);
|
||||
options->input_total_size += input_file_size;
|
||||
if (cs_compress(options->input_files[i], output_full_path, parameters)) {
|
||||
compressed_files++;
|
||||
output_file_size = get_file_size(output_full_path);
|
||||
options->output_total_size += output_file_size;
|
||||
|
||||
fprintf(stdout, "%s -> %s [%.2f%%]\n",
|
||||
get_human_size(input_file_size),
|
||||
get_human_size(output_file_size),
|
||||
((float) output_file_size - input_file_size) * 100 / input_file_size);
|
||||
} else {
|
||||
options->input_total_size -= get_file_size(options->input_files[i]);
|
||||
}
|
||||
|
||||
return status;
|
||||
free(output_full_path);
|
||||
}
|
||||
|
||||
return compressed_files;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -3,12 +3,15 @@
|
|||
|
||||
#include <caesium.h>
|
||||
|
||||
typedef struct cclt_options {
|
||||
typedef struct cclt_options
|
||||
{
|
||||
char **input_files;
|
||||
char *output_folder;
|
||||
bool recursive;
|
||||
bool keep_structure;
|
||||
int files_count;
|
||||
off_t input_total_size;
|
||||
off_t output_total_size;
|
||||
} cclt_options;
|
||||
|
||||
|
||||
|
|
15
src/main.c
15
src/main.c
|
@ -10,7 +10,6 @@
|
|||
int main(int argc, char* argv[]) {
|
||||
errno = 0;
|
||||
long execution_ms = 0;
|
||||
int compression_status = 0;
|
||||
cs_image_pars compress_options;
|
||||
cclt_options options;
|
||||
|
||||
|
@ -20,8 +19,7 @@ int main(int argc, char* argv[]) {
|
|||
//Start a timer before calling the compression
|
||||
clock_t start = clock(), diff;
|
||||
|
||||
//TODO Compress here
|
||||
compression_status = start_compression(&options, &compress_options);
|
||||
start_compression(&options, &compress_options);
|
||||
|
||||
//Cleanup the two memory allocated objects
|
||||
free(options.output_folder);
|
||||
|
@ -32,9 +30,14 @@ int main(int argc, char* argv[]) {
|
|||
execution_ms = diff * 1000 / CLOCKS_PER_SEC;
|
||||
|
||||
//Output the compression results
|
||||
fprintf(stdout,
|
||||
"Performed in %lum%lus%lums\n",
|
||||
execution_ms / 1000 / 60, execution_ms / 1000 % 60, execution_ms % 1000);
|
||||
|
||||
fprintf(stdout, "-------------------------------\nCompression completed in "
|
||||
"%lum%lus%lums\n%s -> %s [%.2f%% | %s]\n",
|
||||
execution_ms / 1000 / 60, execution_ms / 1000 % 60, execution_ms % 1000,
|
||||
get_human_size(options.input_total_size), get_human_size(options.output_total_size),
|
||||
((float)options.output_total_size - options.input_total_size) * 100 / options.input_total_size,
|
||||
get_human_size((options.output_total_size - options.input_total_size)));
|
||||
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
60
src/utils.c
60
src/utils.c
|
@ -3,6 +3,7 @@
|
|||
#include <sys/stat.h>
|
||||
#include <caesium.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include "utils.h"
|
||||
#include "tinydir.h"
|
||||
|
||||
|
@ -15,31 +16,27 @@ void print_help()
|
|||
"Compress your pictures up to 90%% without visible quality loss.\n\n"
|
||||
|
||||
"Options:\n"
|
||||
"\t-q, --quality\t\t\tset output file quality between [0-100], 0 for optimization\n"
|
||||
"\t-e, --exif\t\t\t\tkeeps EXIF info during compression\n"
|
||||
"\t-o, --output\t\t\toutput folder\n"
|
||||
"\t-R, --recursive\t\t\tif input is a folder, scan subfolders too\n"
|
||||
"\t-q, --quality\t\tset output file quality between [0-100], 0 for optimization\n"
|
||||
"\t-e, --exif\t\tkeeps EXIF info during compression\n"
|
||||
"\t-o, --output\t\toutput folder\n"
|
||||
"\t-R, --recursive\t\tif input is a folder, scan subfolders too\n"
|
||||
//TODO Remove this warning
|
||||
"\t-S, --keep-structure\tkeep the folder structure [Not active yet], use with -R\n"
|
||||
"\t-h, --help\t\t\t\tdisplay this help and exit\n"
|
||||
"\t-v, --version\t\t\toutput version information and exit\n\n");
|
||||
"\t-h, --help\t\tdisplay this help and exit\n"
|
||||
"\t-v, --version\t\toutput version information and exit\n\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
int is_directory(const char *path)
|
||||
bool is_directory(const char *path)
|
||||
{
|
||||
tinydir_dir dir;
|
||||
tinydir_file file;
|
||||
bool is_dir = false;
|
||||
|
||||
tinydir_open(&dir, path);
|
||||
if (tinydir_file_open(&file, path) == -1) {
|
||||
//TODO Error
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
tinydir_readfile(&dir, &file);
|
||||
is_dir = (bool) file.is_dir;
|
||||
|
||||
tinydir_close(&dir);
|
||||
|
||||
return is_dir;
|
||||
return (bool) file.is_dir;
|
||||
}
|
||||
|
||||
int scan_folder(const char *directory, cclt_options *options, bool recursive)
|
||||
|
@ -114,3 +111,34 @@ char *get_filename(char *full_path)
|
|||
return token;
|
||||
}
|
||||
|
||||
off_t get_file_size(const char *path)
|
||||
{
|
||||
tinydir_file file;
|
||||
|
||||
if (tinydir_file_open(&file, path) == -1) {
|
||||
//TODO Error
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return file._s.st_size;
|
||||
}
|
||||
|
||||
char* get_human_size(off_t size) {
|
||||
//We should not get more than TB images
|
||||
char* unit[5] = {"B", "KB", "MB", "GB", "TB"};
|
||||
//Index of the array containing the correct unit
|
||||
double order = floor(log2(labs(size)) / 10);
|
||||
//Alloc enough size for the final string
|
||||
char* final = (char*) malloc(((int) (floor(log10(labs(size))) + 4)) * sizeof(char));
|
||||
|
||||
//If the order exceeds 4, something is fishy
|
||||
if (order > 4) {
|
||||
order = 4;
|
||||
}
|
||||
|
||||
//Copy the formatted string into the buffer
|
||||
sprintf(final, "%.2f %s", size / (pow(1024, order)), unit[(int)order]);
|
||||
//And return it
|
||||
return final;
|
||||
}
|
||||
|
||||
|
|
10
src/utils.h
10
src/utils.h
|
@ -7,13 +7,9 @@
|
|||
|
||||
#include "helper.h"
|
||||
|
||||
#define APP_VERSION_STRING "0.10.0"
|
||||
#define APP_VERSION_NUMBER 0100
|
||||
#define BUILD 20161215
|
||||
|
||||
void print_help();
|
||||
|
||||
int is_directory(const char *path);
|
||||
bool is_directory(const char *path);
|
||||
|
||||
int scan_folder(const char *directory, cclt_options *options, bool recursive);
|
||||
|
||||
|
@ -21,5 +17,9 @@ int mkpath(const char *pathname, mode_t mode);
|
|||
|
||||
char *get_filename(char * full_path);
|
||||
|
||||
off_t get_file_size(const char *path);
|
||||
|
||||
char* get_human_size(off_t size);
|
||||
|
||||
|
||||
#endif //CAESIUM_CLT_UTILS_H
|
||||
|
|
Loading…
Reference in New Issue