Code style adjustments
This commit is contained in:
parent
9326392bb3
commit
0ac1a50f1e
|
@ -18,7 +18,8 @@
|
||||||
#include "png.h"
|
#include "png.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
|
||||||
void initialize_jpeg_parameters(cclt_parameters* par) {
|
void initialize_jpeg_parameters(cclt_parameters* par)
|
||||||
|
{
|
||||||
par->jpeg.quality = 0;
|
par->jpeg.quality = 0;
|
||||||
par->jpeg.width = 0;
|
par->jpeg.width = 0;
|
||||||
par->jpeg.height = 0;
|
par->jpeg.height = 0;
|
||||||
|
@ -28,7 +29,8 @@ void initialize_jpeg_parameters(cclt_parameters* par) {
|
||||||
par->jpeg.lossless = false;
|
par->jpeg.lossless = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void initialize_png_parameters(cclt_parameters* par) {
|
void initialize_png_parameters(cclt_parameters* par)
|
||||||
|
{
|
||||||
par->png.iterations = 10;
|
par->png.iterations = 10;
|
||||||
par->png.iterations_large = 5;
|
par->png.iterations_large = 5;
|
||||||
par->png.block_split_strategy = 4;
|
par->png.block_split_strategy = 4;
|
||||||
|
@ -37,7 +39,8 @@ void initialize_png_parameters(cclt_parameters* par) {
|
||||||
par->png.auto_filter_strategy = 1;
|
par->png.auto_filter_strategy = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
cclt_parameters initialize_compression_parameters() {
|
cclt_parameters initialize_compression_parameters()
|
||||||
|
{
|
||||||
cclt_parameters par;
|
cclt_parameters par;
|
||||||
|
|
||||||
initialize_jpeg_parameters(&par);
|
initialize_jpeg_parameters(&par);
|
||||||
|
@ -52,7 +55,8 @@ cclt_parameters initialize_compression_parameters() {
|
||||||
return par;
|
return par;
|
||||||
}
|
}
|
||||||
|
|
||||||
void validate_parameters(cclt_parameters* pars) {
|
void validate_parameters(cclt_parameters* pars)
|
||||||
|
{
|
||||||
//Either -l or -q must be set but not together
|
//Either -l or -q must be set but not together
|
||||||
if (!((pars->jpeg.lossless) ^ (pars->jpeg.quality > 0))) {
|
if (!((pars->jpeg.lossless) ^ (pars->jpeg.quality > 0))) {
|
||||||
//Both or none are set
|
//Both or none are set
|
||||||
|
@ -80,59 +84,58 @@ void validate_parameters(cclt_parameters* pars) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cclt_parameters parse_arguments(int argc, char* argv[]) {
|
cclt_parameters parse_arguments(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
|
||||||
//Initialize default params
|
//Initialize default params
|
||||||
cclt_parameters parameters = initialize_compression_parameters();
|
cclt_parameters parameters = initialize_compression_parameters();
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
while (optind < argc) {
|
while (optind < argc) {
|
||||||
if ((c = getopt (argc, argv, "q:velo:s:hR")) != -1) {
|
if ((c = getopt(argc, argv, "q:velo:s:hR")) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'v':
|
case 'v':
|
||||||
printf("%s-%d\n", APP_VERSION, BUILD);
|
printf("%s-%d\n", APP_VERSION, BUILD);
|
||||||
exit(0);
|
exit(0);
|
||||||
case '?':
|
case '?':
|
||||||
if (optopt == 'q' || optopt == 'o' || optopt == 's') {
|
if (optopt == 'q' || optopt == 'o' || optopt == 's') {
|
||||||
trigger_error(6, true, optopt);
|
trigger_error(6, true, optopt);
|
||||||
}
|
} else if (isprint(optopt)) {
|
||||||
else if (isprint(optopt)) {
|
trigger_error(100, false, optopt);
|
||||||
trigger_error(100, false, optopt);
|
} else {
|
||||||
}
|
trigger_error(101, false, optopt);
|
||||||
else {
|
}
|
||||||
trigger_error(101, false, optopt);
|
break;
|
||||||
}
|
case ':':
|
||||||
break;
|
trigger_error(102, false);
|
||||||
case ':':
|
break;
|
||||||
trigger_error(102, false);
|
case 'q':
|
||||||
break;
|
parameters.jpeg.quality = string_to_int(optarg);
|
||||||
case 'q':
|
break;
|
||||||
parameters.jpeg.quality = string_to_int(optarg);
|
case 'e':
|
||||||
break;
|
parameters.jpeg.exif_copy = true;
|
||||||
case 'e':
|
break;
|
||||||
parameters.jpeg.exif_copy = true;
|
case 'l':
|
||||||
break;
|
parameters.jpeg.lossless = true;
|
||||||
case 'l':
|
break;
|
||||||
parameters.jpeg.lossless = true;
|
case 'o':
|
||||||
break;
|
parameters.output_folder = optarg;
|
||||||
case 'o':
|
break;
|
||||||
parameters.output_folder = optarg;
|
case 'h':
|
||||||
break;
|
print_help();
|
||||||
case 'h':
|
break;
|
||||||
print_help();
|
case 'R':
|
||||||
break;
|
parameters.recursive = true;
|
||||||
case 'R':
|
break;
|
||||||
parameters.recursive = true;
|
case 'S':
|
||||||
break;
|
parameters.structure = true;
|
||||||
case 'S':
|
break;
|
||||||
parameters.structure = true;
|
default:
|
||||||
break;
|
abort();
|
||||||
default:
|
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
parameters.input_files = (char**) malloc ((argc - optind) * sizeof (char*));
|
parameters.input_files = (char**)malloc((argc - optind) * sizeof(char*));
|
||||||
while (optind < argc) {
|
while (optind < argc) {
|
||||||
if (is_directory(argv[optind])) {
|
if (is_directory(argv[optind])) {
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
|
@ -144,7 +147,7 @@ cclt_parameters parse_arguments(int argc, char* argv[]) {
|
||||||
scan_folder(¶meters, argv[optind], parameters.recursive);
|
scan_folder(¶meters, argv[optind], parameters.recursive);
|
||||||
return parameters;
|
return parameters;
|
||||||
} else {
|
} else {
|
||||||
parameters.input_files[i] = (char*) malloc (strlen(argv[optind]) * sizeof(char)); //TODO Necessary??
|
parameters.input_files[i] = (char*)malloc(strlen(argv[optind]) * sizeof(char)); //TODO Necessary??
|
||||||
parameters.input_files[i] = argv[optind];
|
parameters.input_files[i] = argv[optind];
|
||||||
i++;
|
i++;
|
||||||
parameters.input_files_count = i;
|
parameters.input_files_count = i;
|
||||||
|
@ -160,10 +163,11 @@ cclt_parameters parse_arguments(int argc, char* argv[]) {
|
||||||
return parameters;
|
return parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cclt_compress_routine(char* input, char* output, cclt_parameters* pars) {
|
int cclt_compress_routine(char* input, char* output, cclt_parameters* pars)
|
||||||
|
{
|
||||||
//Detect which image type are we compressing
|
//Detect which image type are we compressing
|
||||||
enum image_type type = detect_image_type(input);
|
enum image_type type = detect_image_type(input);
|
||||||
char* exif_orig = (char*) malloc(strlen(input) * sizeof(char));
|
char* exif_orig = (char*)malloc(strlen(input) * sizeof(char));
|
||||||
strcpy(exif_orig, input);
|
strcpy(exif_orig, input);
|
||||||
|
|
||||||
if (type == JPEG) {
|
if (type == JPEG) {
|
||||||
|
@ -187,8 +191,8 @@ int cclt_compress_routine(char* input, char* output, cclt_parameters* pars) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cclt_start(cclt_parameters* pars, off_t* i_t_size, off_t* o_t_size) {
|
void cclt_start(cclt_parameters* pars, off_t* i_t_size, off_t* o_t_size)
|
||||||
|
{
|
||||||
struct stat st_buf;
|
struct stat st_buf;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
|
@ -204,7 +208,7 @@ void cclt_start(cclt_parameters* pars, off_t* i_t_size, off_t* o_t_size) {
|
||||||
off_t i_size, o_size;
|
off_t i_size, o_size;
|
||||||
int status; //Pointer for stat() call
|
int status; //Pointer for stat() call
|
||||||
|
|
||||||
char* output_filename = (char*) malloc ((strlen(pars->output_folder) + 1) * sizeof(char));
|
char* output_filename = (char*)malloc((strlen(pars->output_folder) + 1) * sizeof(char));
|
||||||
|
|
||||||
strcpy(output_filename, pars->output_folder);
|
strcpy(output_filename, pars->output_folder);
|
||||||
|
|
||||||
|
@ -222,10 +226,10 @@ void cclt_start(cclt_parameters* pars, off_t* i_t_size, off_t* o_t_size) {
|
||||||
trigger_error(11, true, pars->input_files[i]);
|
trigger_error(11, true, pars->input_files[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Check if we ran into a folder
|
//Check if we ran into a folder
|
||||||
//TODO Check symlinks too
|
//TODO Check symlinks too
|
||||||
if (is_directory(pars->input_files[i])) {
|
if (is_directory(pars->input_files[i])) {
|
||||||
//Folder found, but we don't need it here
|
//Folder found, but we don't need it here
|
||||||
i++;
|
i++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -236,10 +240,10 @@ void cclt_start(cclt_parameters* pars, off_t* i_t_size, off_t* o_t_size) {
|
||||||
|
|
||||||
//TODO Do we want a more verbose output?
|
//TODO Do we want a more verbose output?
|
||||||
fprintf(stdout, "(%d/%d) %s -> %s\n",
|
fprintf(stdout, "(%d/%d) %s -> %s\n",
|
||||||
i + 1,
|
i + 1,
|
||||||
pars->input_files_count,
|
pars->input_files_count,
|
||||||
pars->input_files[i],
|
pars->input_files[i],
|
||||||
output_filename);
|
output_filename);
|
||||||
|
|
||||||
int routine = cclt_compress_routine(pars->input_files[i], output_filename, pars);
|
int routine = cclt_compress_routine(pars->input_files[i], output_filename, pars);
|
||||||
if (routine == -1) {
|
if (routine == -1) {
|
||||||
|
@ -257,11 +261,10 @@ void cclt_start(cclt_parameters* pars, off_t* i_t_size, off_t* o_t_size) {
|
||||||
*(o_t_size) += o_size;
|
*(o_t_size) += o_size;
|
||||||
|
|
||||||
fprintf(stdout, "%s -> %s [%.2f%%]\n",
|
fprintf(stdout, "%s -> %s [%.2f%%]\n",
|
||||||
get_human_size(i_size),
|
get_human_size(i_size),
|
||||||
get_human_size(o_size),
|
get_human_size(o_size),
|
||||||
((float) o_size - i_size) * 100 / i_size);
|
((float)o_size - i_size) * 100 / i_size);
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
229
src/error.c
229
src/error.c
|
@ -11,110 +11,137 @@
|
||||||
|
|
||||||
#define parse_error_level(level) ((level) ? "ERROR" : "WARNING")
|
#define parse_error_level(level) ((level) ? "ERROR" : "WARNING")
|
||||||
|
|
||||||
void trigger_error(int code, bool is_critical, ...) {
|
void trigger_error(int code, bool is_critical, ...)
|
||||||
va_list args;
|
{
|
||||||
va_start(args, is_critical);
|
va_list args;
|
||||||
|
va_start(args, is_critical);
|
||||||
|
|
||||||
fprintf(stderr, "%s - %d: ",
|
fprintf(stderr, "%s - %d: ",
|
||||||
parse_error_level(is_critical),
|
parse_error_level(is_critical),
|
||||||
code);
|
code);
|
||||||
|
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case 1:
|
case 1:
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"-l option can't be used with -q. Either use one or the other.");
|
"-l option can't be used with -q. Either use one or the other.");
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Either -l or -q must be set.");
|
"Either -l or -q must be set.");
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Quality must be within a [1-100] range.");
|
"Quality must be within a [1-100] range.");
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"No -o option pointing to the destination folder.");
|
"No -o option pointing to the destination folder.");
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Failed to create output directory. Permission issue?");
|
"Failed to create output directory. Permission issue?");
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
vfprintf(stderr,
|
vfprintf(stderr,
|
||||||
"Option -%c requires an argument.", args);
|
"Option -%c requires an argument.", args);
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 7:
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"No input files.");
|
"No digits were found for -q option.");
|
||||||
break;
|
break;
|
||||||
case 11:
|
case 8:
|
||||||
vfprintf(stderr,
|
fprintf(stderr,
|
||||||
"Failed to get input file stats: %s", args);
|
"Cannot parse quality value.");
|
||||||
break;
|
break;
|
||||||
case 12:
|
case 9:
|
||||||
vfprintf(stderr,
|
fprintf(stderr,
|
||||||
"Failed to get output file stats: %s", args);
|
"No input files.");
|
||||||
break;
|
break;
|
||||||
case 13:
|
case 11:
|
||||||
vfprintf(stderr,
|
vfprintf(stderr,
|
||||||
"Failed to open file (markers): %s", args);
|
"Failed to get input file stats: %s", args);
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 12:
|
||||||
vfprintf(stderr,
|
vfprintf(stderr,
|
||||||
"Failed to open PNG file: %s", args);
|
"Failed to get output file stats: %s", args);
|
||||||
break;
|
break;
|
||||||
case 17:
|
case 13:
|
||||||
fprintf(stderr,
|
vfprintf(stderr,
|
||||||
"Error while optimizing PNG.");
|
"Failed to open file (markers): %s", args);
|
||||||
break;
|
break;
|
||||||
case 18:
|
case 14:
|
||||||
vfprintf(stderr,
|
vfprintf(stderr,
|
||||||
"Error while writing PNG: %s", args);
|
"Cannot open input file for type detection: %s", args);
|
||||||
case 20:
|
break;
|
||||||
fprintf(stderr,
|
case 15:
|
||||||
"Found folder along with input files.");
|
vfprintf(stderr,
|
||||||
case 100:
|
"Cannot read file type: %s", args);
|
||||||
vfprintf(stderr,
|
break;
|
||||||
"Unknown option `-%c'.", args);
|
case 16:
|
||||||
break;
|
vfprintf(stderr,
|
||||||
case 101:
|
"Failed to open PNG file: %s", args);
|
||||||
vfprintf(stderr,
|
break;
|
||||||
"Unknown option character `\\x%x'.", args);
|
case 17:
|
||||||
break;
|
fprintf(stderr,
|
||||||
case 102:
|
"Error while optimizing PNG.");
|
||||||
fprintf(stderr,
|
break;
|
||||||
"Parameter expected.");
|
case 18:
|
||||||
break;
|
vfprintf(stderr,
|
||||||
case 103:
|
"Error while writing PNG: %s", args);
|
||||||
fprintf(stderr,
|
break;
|
||||||
"Folder found, skipping all other inputs.");
|
case 19:
|
||||||
break;
|
vfprintf(stderr,
|
||||||
case 104:
|
"Failed to open folder: %s", args);
|
||||||
vfprintf(stderr,
|
break;
|
||||||
"Unknown file type: %s", args);
|
case 20:
|
||||||
break;
|
fprintf(stderr,
|
||||||
case 105:
|
"Found folder along with input files.");
|
||||||
vfprintf(stderr,
|
break;
|
||||||
"Failed to open file (input): %s", args);
|
case 21:
|
||||||
break;
|
fprintf(stderr,
|
||||||
case 106:
|
"Do you really have such a huge file?");
|
||||||
vfprintf(stderr,
|
break;
|
||||||
"Failed to open file (output): %s", args);
|
case 100:
|
||||||
break;
|
vfprintf(stderr,
|
||||||
default:
|
"Unknown option `-%c'.", args);
|
||||||
//Every unlisted code is critical
|
break;
|
||||||
is_critical = true;
|
case 101:
|
||||||
fprintf(stderr,
|
vfprintf(stderr,
|
||||||
"Cs-137 spreading out. Good luck.");
|
"Unknown option character `\\x%x'.", args);
|
||||||
break;
|
break;
|
||||||
}
|
case 102:
|
||||||
|
fprintf(stderr,
|
||||||
|
"Parameter expected.");
|
||||||
|
break;
|
||||||
|
case 103:
|
||||||
|
fprintf(stderr,
|
||||||
|
"Folder found, skipping all other inputs.");
|
||||||
|
break;
|
||||||
|
case 104:
|
||||||
|
vfprintf(stderr,
|
||||||
|
"Unknown file type: %s", args);
|
||||||
|
break;
|
||||||
|
case 105:
|
||||||
|
vfprintf(stderr,
|
||||||
|
"Failed to open file (input): %s", args);
|
||||||
|
break;
|
||||||
|
case 106:
|
||||||
|
vfprintf(stderr,
|
||||||
|
"Failed to open file (output): %s", args);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//Every unlisted code is critical
|
||||||
|
is_critical = true;
|
||||||
|
fprintf(stderr,
|
||||||
|
"Cs-137 spreading out. Good luck.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
if (is_critical) {
|
if (is_critical) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
90
src/jpeg.c
90
src/jpeg.c
|
@ -13,7 +13,8 @@
|
||||||
|
|
||||||
//TODO Error handling
|
//TODO Error handling
|
||||||
|
|
||||||
struct jpeg_decompress_struct cclt_get_markers(char* input) {
|
struct jpeg_decompress_struct cclt_get_markers(char* input)
|
||||||
|
{
|
||||||
FILE* fp;
|
FILE* fp;
|
||||||
struct jpeg_decompress_struct einfo;
|
struct jpeg_decompress_struct einfo;
|
||||||
struct jpeg_error_mgr eerr;
|
struct jpeg_error_mgr eerr;
|
||||||
|
@ -21,7 +22,7 @@ struct jpeg_decompress_struct cclt_get_markers(char* input) {
|
||||||
|
|
||||||
jpeg_create_decompress(&einfo);
|
jpeg_create_decompress(&einfo);
|
||||||
|
|
||||||
//Open the input file
|
//Open the input file
|
||||||
fp = fopen(input, "r");
|
fp = fopen(input, "r");
|
||||||
|
|
||||||
//Check for errors
|
//Check for errors
|
||||||
|
@ -45,7 +46,8 @@ struct jpeg_decompress_struct cclt_get_markers(char* input) {
|
||||||
return einfo;
|
return einfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cclt_jpeg_optimize(char* input_file, char* output_file, int exif_flag, char* exif_src) {
|
int cclt_jpeg_optimize(char* input_file, char* output_file, int exif_flag, char* exif_src)
|
||||||
|
{
|
||||||
//TODO Bug on normal compress: the input file is a bogus long string
|
//TODO Bug on normal compress: the input file is a bogus long string
|
||||||
// Happened with a (bugged) server connection
|
// Happened with a (bugged) server connection
|
||||||
//File pointer for both input and output
|
//File pointer for both input and output
|
||||||
|
@ -68,7 +70,6 @@ int cclt_jpeg_optimize(char* input_file, char* output_file, int exif_flag, char*
|
||||||
dstinfo.err = jpeg_std_error(&jdsterr);
|
dstinfo.err = jpeg_std_error(&jdsterr);
|
||||||
jpeg_create_compress(&dstinfo);
|
jpeg_create_compress(&dstinfo);
|
||||||
|
|
||||||
|
|
||||||
//Open the input file
|
//Open the input file
|
||||||
fp = fopen(input_file, "r");
|
fp = fopen(input_file, "r");
|
||||||
|
|
||||||
|
@ -89,8 +90,7 @@ int cclt_jpeg_optimize(char* input_file, char* output_file, int exif_flag, char*
|
||||||
}
|
}
|
||||||
|
|
||||||
//Read the input headers
|
//Read the input headers
|
||||||
(void) jpeg_read_header(&srcinfo, TRUE);
|
(void)jpeg_read_header(&srcinfo, TRUE);
|
||||||
|
|
||||||
|
|
||||||
//Read input coefficents
|
//Read input coefficents
|
||||||
src_coef_arrays = jpeg_read_coefficients(&srcinfo);
|
src_coef_arrays = jpeg_read_coefficients(&srcinfo);
|
||||||
|
@ -139,7 +139,7 @@ int cclt_jpeg_optimize(char* input_file, char* output_file, int exif_flag, char*
|
||||||
//Finish and free
|
//Finish and free
|
||||||
jpeg_finish_compress(&dstinfo);
|
jpeg_finish_compress(&dstinfo);
|
||||||
jpeg_destroy_compress(&dstinfo);
|
jpeg_destroy_compress(&dstinfo);
|
||||||
(void) jpeg_finish_decompress(&srcinfo);
|
(void)jpeg_finish_decompress(&srcinfo);
|
||||||
jpeg_destroy_decompress(&srcinfo);
|
jpeg_destroy_decompress(&srcinfo);
|
||||||
|
|
||||||
//Close the output file
|
//Close the output file
|
||||||
|
@ -148,7 +148,8 @@ int cclt_jpeg_optimize(char* input_file, char* output_file, int exif_flag, char*
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cclt_jpeg_compress(char* output_file, unsigned char* image_buffer, cclt_jpeg_parameters* pars) {
|
void cclt_jpeg_compress(char* output_file, unsigned char* image_buffer, cclt_jpeg_parameters* pars)
|
||||||
|
{
|
||||||
FILE* fp;
|
FILE* fp;
|
||||||
tjhandle tjCompressHandle;
|
tjhandle tjCompressHandle;
|
||||||
unsigned char* output_buffer;
|
unsigned char* output_buffer;
|
||||||
|
@ -159,38 +160,38 @@ void cclt_jpeg_compress(char* output_file, unsigned char* image_buffer, cclt_jpe
|
||||||
//Check for errors
|
//Check for errors
|
||||||
//TODO Use UNIX error messages
|
//TODO Use UNIX error messages
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
trigger_error(106, true, output_file);
|
trigger_error(106, true, output_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
output_buffer = NULL;
|
output_buffer = NULL;
|
||||||
tjCompressHandle = tjInitCompress();
|
tjCompressHandle = tjInitCompress();
|
||||||
|
|
||||||
//TODO Error checks
|
//TODO Error checks
|
||||||
tjCompress2(tjCompressHandle,
|
tjCompress2(tjCompressHandle,
|
||||||
image_buffer,
|
image_buffer,
|
||||||
pars->width,
|
pars->width,
|
||||||
0,
|
0,
|
||||||
pars->height,
|
pars->height,
|
||||||
pars->color_space,
|
pars->color_space,
|
||||||
&output_buffer,
|
&output_buffer,
|
||||||
&output_size,
|
&output_size,
|
||||||
pars->subsample,
|
pars->subsample,
|
||||||
pars->quality,
|
pars->quality,
|
||||||
pars->dct_method);
|
pars->dct_method);
|
||||||
|
|
||||||
fwrite(output_buffer, output_size, 1, fp);
|
fwrite(output_buffer, output_size, 1, fp);
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
tjDestroy(tjCompressHandle);
|
|
||||||
tjFree(output_buffer);
|
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
tjDestroy(tjCompressHandle);
|
||||||
|
tjFree(output_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char* cclt_jpeg_decompress(char* fileName, cclt_jpeg_parameters* pars) {
|
unsigned char* cclt_jpeg_decompress(char* fileName, cclt_jpeg_parameters* pars)
|
||||||
|
{
|
||||||
|
|
||||||
//TODO I/O Error handling
|
//TODO I/O Error handling
|
||||||
|
|
||||||
FILE *file = NULL;
|
FILE* file = NULL;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
long int sourceJpegBufferSize = 0;
|
long int sourceJpegBufferSize = 0;
|
||||||
unsigned char* sourceJpegBuffer = NULL;
|
unsigned char* sourceJpegBuffer = NULL;
|
||||||
|
@ -233,7 +234,8 @@ unsigned char* cclt_jpeg_decompress(char* fileName, cclt_jpeg_parameters* pars)
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void jcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo) {
|
void jcopy_markers_execute(j_decompress_ptr srcinfo, j_compress_ptr dstinfo)
|
||||||
|
{
|
||||||
jpeg_saved_marker_ptr marker;
|
jpeg_saved_marker_ptr marker;
|
||||||
|
|
||||||
/* In the current implementation, we don't actually need to examine the
|
/* In the current implementation, we don't actually need to examine the
|
||||||
|
@ -242,25 +244,11 @@ void jcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo) {
|
||||||
* if the encoder library already wrote one.
|
* if the encoder library already wrote one.
|
||||||
*/
|
*/
|
||||||
for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) {
|
for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) {
|
||||||
if (dstinfo->write_JFIF_header &&
|
if (dstinfo->write_JFIF_header && marker->marker == JPEG_APP0 && marker->data_length >= 5 && GETJOCTET(marker->data[0]) == 0x4A && GETJOCTET(marker->data[1]) == 0x46 && GETJOCTET(marker->data[2]) == 0x49 && GETJOCTET(marker->data[3]) == 0x46 && GETJOCTET(marker->data[4]) == 0)
|
||||||
marker->marker == JPEG_APP0 &&
|
continue; /* reject duplicate JFIF */
|
||||||
marker->data_length >= 5 &&
|
if (dstinfo->write_Adobe_marker && marker->marker == JPEG_APP0 + 14 && marker->data_length >= 5 && GETJOCTET(marker->data[0]) == 0x41 && GETJOCTET(marker->data[1]) == 0x64 && GETJOCTET(marker->data[2]) == 0x6F && GETJOCTET(marker->data[3]) == 0x62 && GETJOCTET(marker->data[4]) == 0x65)
|
||||||
GETJOCTET(marker->data[0]) == 0x4A &&
|
continue; /* reject duplicate Adobe */
|
||||||
GETJOCTET(marker->data[1]) == 0x46 &&
|
|
||||||
GETJOCTET(marker->data[2]) == 0x49 &&
|
|
||||||
GETJOCTET(marker->data[3]) == 0x46 &&
|
|
||||||
GETJOCTET(marker->data[4]) == 0)
|
|
||||||
continue; /* reject duplicate JFIF */
|
|
||||||
if (dstinfo->write_Adobe_marker &&
|
|
||||||
marker->marker == JPEG_APP0+14 &&
|
|
||||||
marker->data_length >= 5 &&
|
|
||||||
GETJOCTET(marker->data[0]) == 0x41 &&
|
|
||||||
GETJOCTET(marker->data[1]) == 0x64 &&
|
|
||||||
GETJOCTET(marker->data[2]) == 0x6F &&
|
|
||||||
GETJOCTET(marker->data[3]) == 0x62 &&
|
|
||||||
GETJOCTET(marker->data[4]) == 0x65)
|
|
||||||
continue; /* reject duplicate Adobe */
|
|
||||||
jpeg_write_marker(dstinfo, marker->marker,
|
jpeg_write_marker(dstinfo, marker->marker,
|
||||||
marker->data, marker->data_length);
|
marker->data, marker->data_length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@ int cclt_jpeg_optimize(char* input_file, char* output_file, int exif_flag, char*
|
||||||
struct jpeg_decompress_struct cclt_get_markers(char* input);
|
struct jpeg_decompress_struct cclt_get_markers(char* input);
|
||||||
void cclt_jpeg_compress(char* output_file, unsigned char* image_buffer, cclt_jpeg_parameters* pars);
|
void cclt_jpeg_compress(char* output_file, unsigned char* image_buffer, cclt_jpeg_parameters* pars);
|
||||||
unsigned char* cclt_jpeg_decompress(char* fileName, cclt_jpeg_parameters* pars);
|
unsigned char* cclt_jpeg_decompress(char* fileName, cclt_jpeg_parameters* pars);
|
||||||
void jcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo);
|
void jcopy_markers_execute(j_decompress_ptr srcinfo, j_compress_ptr dstinfo);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
14
src/main.c
14
src/main.c
|
@ -28,7 +28,8 @@
|
||||||
// we're gonna go in a infinite loop
|
// we're gonna go in a infinite loop
|
||||||
// TODO Trigger a warning if you are overwriting files
|
// TODO Trigger a warning if you are overwriting files
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
errno = 0;
|
errno = 0;
|
||||||
off_t i_t_size = 0, o_t_size = 0;
|
off_t i_t_size = 0, o_t_size = 0;
|
||||||
// Parse arguments
|
// Parse arguments
|
||||||
|
@ -42,12 +43,13 @@ int main(int argc, char *argv[]) {
|
||||||
diff = clock() - start;
|
diff = clock() - start;
|
||||||
long msec = diff * 1000 / CLOCKS_PER_SEC;
|
long msec = diff * 1000 / CLOCKS_PER_SEC;
|
||||||
|
|
||||||
fprintf(stdout, "-------------------------------\nCompression completed in "
|
fprintf(stdout, "-------------------------------\n"
|
||||||
|
"Compression completed in "
|
||||||
"%lum%lus%lums\n%s -> %s [%.2f%% | %s]\n",
|
"%lum%lus%lums\n%s -> %s [%.2f%% | %s]\n",
|
||||||
msec / 1000 / 60, msec / 1000 % 60, msec % 1000,
|
msec / 1000 / 60, msec / 1000 % 60, msec % 1000,
|
||||||
get_human_size((long)i_t_size), get_human_size((long)o_t_size),
|
get_human_size((long)i_t_size), get_human_size((long)o_t_size),
|
||||||
((float)o_t_size - i_t_size) * 100 / i_t_size,
|
((float)o_t_size - i_t_size) * 100 / i_t_size,
|
||||||
get_human_size(((long)o_t_size - i_t_size)));
|
get_human_size(((long)o_t_size - i_t_size)));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
14
src/png.c
14
src/png.c
|
@ -7,7 +7,8 @@
|
||||||
#include "png.h"
|
#include "png.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
|
||||||
void cclt_png_optimize(char* input, char* output, cclt_png_parameters* pars) {
|
void cclt_png_optimize(char* input, char* output, cclt_png_parameters* pars)
|
||||||
|
{
|
||||||
//TODO Error handling
|
//TODO Error handling
|
||||||
CZopfliPNGOptions png_options;
|
CZopfliPNGOptions png_options;
|
||||||
|
|
||||||
|
@ -33,11 +34,12 @@ void cclt_png_optimize(char* input, char* output, cclt_png_parameters* pars) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CZopfliPNGOptimize(orig_buffer,
|
if (CZopfliPNGOptimize(orig_buffer,
|
||||||
orig_buffer_size,
|
orig_buffer_size,
|
||||||
&png_options,
|
&png_options,
|
||||||
0,
|
0,
|
||||||
&resultpng,
|
&resultpng,
|
||||||
&resultpng_size) != 0) {
|
&resultpng_size)
|
||||||
|
!= 0) {
|
||||||
trigger_error(17, true);
|
trigger_error(17, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
106
src/utils.c
106
src/utils.c
|
@ -14,68 +14,69 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#ifdef __linux
|
#ifdef __linux
|
||||||
#include <linux/limits.h>
|
#include <linux/limits.h>
|
||||||
#elif __APPLE__
|
#elif __APPLE__
|
||||||
#include <sys/syslimits.h>
|
#include <sys/syslimits.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
int string_to_int(char* in_string) {
|
int string_to_int(char* in_string)
|
||||||
|
{
|
||||||
long value = 0;
|
long value = 0;
|
||||||
char* endptr;
|
char* endptr;
|
||||||
errno = 0; //Error checking
|
|
||||||
|
|
||||||
value = strtol(in_string, &endptr, 0); //Convert the string
|
value = strtol(in_string, &endptr, 0); //Convert the string
|
||||||
|
|
||||||
//Check errors
|
//Check errors
|
||||||
if ((errno == ERANGE) || (errno != 0 && value == 0)) {
|
if ((errno == ERANGE) || (errno != 0 && value == 0)) {
|
||||||
fprintf(stderr, "[ERROR] Cannot parse quality value.\n");
|
trigger_error(8, true);
|
||||||
exit(-8);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (endptr == in_string) {
|
if (endptr == in_string) {
|
||||||
fprintf(stderr, "[ERROR] Parse error. No digits were found for -q option.\n");
|
trigger_error(7, true);
|
||||||
exit(-7);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_help() {
|
void print_help()
|
||||||
|
{
|
||||||
fprintf(stdout,
|
fprintf(stdout,
|
||||||
"CaesiumCLT - Caesium Command Line Tools\n\n"
|
"CaesiumCLT - Caesium Command Line Tools\n\n"
|
||||||
"Usage: caesiumclt [OPTIONS] INPUT...\n"
|
"Usage: caesiumclt [OPTIONS] INPUT...\n"
|
||||||
"Compress your pictures up to 90%% without visible quality loss.\n\n"
|
"Compress your pictures up to 90%% without visible quality loss.\n\n"
|
||||||
|
|
||||||
"Options:\n"
|
"Options:\n"
|
||||||
"\t-q\tset output file quality between [1-100], JPEG only\n"
|
"\t-q\tset output file quality between [1-100], JPEG only\n"
|
||||||
"\t-e\tkeeps EXIF info during compression\n"
|
"\t-e\tkeeps EXIF info during compression\n"
|
||||||
"\t-o\toutput folder\n"
|
"\t-o\toutput folder\n"
|
||||||
"\t-l\tuse lossless optimization\n"
|
"\t-l\tuse lossless optimization\n"
|
||||||
"\t-R\tif input is a folder, scan subfolders too\n"
|
"\t-R\tif input is a folder, scan subfolders too\n"
|
||||||
//TODO Remove this warning
|
//TODO Remove this warning
|
||||||
"\t-S\tkeep the folder structure [Not active yet]\n"
|
"\t-S\tkeep the folder structure [Not active yet]\n"
|
||||||
"\t-h\tdisplay this help and exit\n"
|
"\t-h\tdisplay this help and exit\n"
|
||||||
"\t-v\toutput version information and exit\n\n");
|
"\t-v\toutput version information and exit\n\n");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO Recheck
|
//TODO Recheck
|
||||||
int mkpath(const char *pathname, mode_t mode) {
|
int mkpath(const char* pathname, mode_t mode)
|
||||||
|
{
|
||||||
|
|
||||||
char parent[PATH_MAX], *p;
|
char parent[PATH_MAX], *p;
|
||||||
/* make a parent directory path */
|
/* make a parent directory path */
|
||||||
strncpy(parent, pathname, sizeof(parent));
|
strncpy(parent, pathname, sizeof(parent));
|
||||||
parent[sizeof(parent) - 1] = '\0';
|
parent[sizeof(parent) - 1] = '\0';
|
||||||
for (p = parent + strlen(parent); *p != '/' && p != parent; p--);
|
for (p = parent + strlen(parent); *p != '/' && p != parent; p--)
|
||||||
|
;
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
/* try make parent directory */
|
/* try make parent directory */
|
||||||
if(p != parent && mkpath(parent, mode) != 0) {
|
if (p != parent && mkpath(parent, mode) != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* make this one if parent has been made */
|
/* make this one if parent has been made */
|
||||||
if(mkdir(pathname, mode) == 0) {
|
if (mkdir(pathname, mode) == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* if it already exists that is fine */
|
/* if it already exists that is fine */
|
||||||
|
@ -85,10 +86,11 @@ int mkpath(const char *pathname, mode_t mode) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void scan_folder(cclt_parameters* parameters, char* basedir, int recur) {
|
void scan_folder(cclt_parameters* parameters, char* basedir, int recur)
|
||||||
//TODO CRITIAL Pass list as 1st parameter
|
{
|
||||||
DIR *dir;
|
//TODO CRITICAL Pass list as 1st parameter
|
||||||
struct dirent *ent;
|
DIR* dir;
|
||||||
|
struct dirent* ent;
|
||||||
char* entpath = NULL;
|
char* entpath = NULL;
|
||||||
struct stat s;
|
struct stat s;
|
||||||
|
|
||||||
|
@ -126,68 +128,68 @@ void scan_folder(cclt_parameters* parameters, char* basedir, int recur) {
|
||||||
parameters->input_files_count++;
|
parameters->input_files_count++;
|
||||||
//Alloc new room for the array
|
//Alloc new room for the array
|
||||||
parameters->input_files = realloc(parameters->input_files, (n + 1) * sizeof(char*));
|
parameters->input_files = realloc(parameters->input_files, (n + 1) * sizeof(char*));
|
||||||
parameters->input_files[n] = (char*) malloc(strlen(entpath) * sizeof(char));
|
parameters->input_files[n] = (char*)malloc(strlen(entpath) * sizeof(char));
|
||||||
//Copy the file path in the array
|
//Copy the file path in the array
|
||||||
parameters->input_files[n] = strcpy(parameters->input_files[n], entpath);
|
parameters->input_files[n] = strcpy(parameters->input_files[n], entpath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "[ERROR] Failed to open folder.\n");
|
trigger_error(19, true, ptr);
|
||||||
exit(-19);
|
|
||||||
}
|
}
|
||||||
free(entpath);
|
free(entpath);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum image_type detect_image_type(char* path) {
|
enum image_type detect_image_type(char* path)
|
||||||
|
{
|
||||||
//Open the file
|
//Open the file
|
||||||
FILE* fp;
|
FILE* fp;
|
||||||
unsigned char* type_buffer = (unsigned char*) malloc(2);
|
enum image_type type = UNKN;
|
||||||
|
|
||||||
|
unsigned char* type_buffer = (unsigned char*)malloc(2);
|
||||||
|
|
||||||
fp = fopen(path, "r");
|
fp = fopen(path, "r");
|
||||||
|
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
fprintf(stderr, "[ERROR] Cannot open input file for type detection.\n");
|
trigger_error(14, true, path);
|
||||||
exit(-14);
|
|
||||||
}
|
}
|
||||||
//Read enough bytes
|
//Read enough bytes
|
||||||
if (fread(type_buffer, 1, 2, fp) < 2) {
|
if (fread(type_buffer, 1, 2, fp) < 2) {
|
||||||
fprintf(stderr, "[ERROR] Cannot read file type.\n");
|
trigger_error(15, true, path);
|
||||||
exit(-15);
|
|
||||||
}
|
}
|
||||||
//We don't need it anymore
|
//We don't need it anymore
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
//Check the bytes against the JPEG and PNG specs
|
//Check the bytes against the JPEG and PNG specs
|
||||||
if (((int) type_buffer[0] == 0xFF) && ((int) type_buffer[1] == 0xD8)) {
|
if (((int)type_buffer[0] == 0xFF) && ((int)type_buffer[1] == 0xD8)) {
|
||||||
free(type_buffer);
|
type = JPEG;
|
||||||
return JPEG;
|
} else if (((int)type_buffer[0] == 0x89) && ((int)type_buffer[1] == 0x50)) {
|
||||||
} else if (((int) type_buffer[0] == 0x89) && ((int) type_buffer[1] == 0x50)) {
|
type = PNG;
|
||||||
free(type_buffer);
|
|
||||||
return PNG;
|
|
||||||
} else {
|
|
||||||
free(type_buffer);
|
|
||||||
return UNKN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(type_buffer);
|
||||||
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
int is_directory(const char *file_path) {
|
int is_directory(const char* file_path)
|
||||||
|
{
|
||||||
struct stat s;
|
struct stat s;
|
||||||
stat(file_path, &s);
|
stat(file_path, &s);
|
||||||
return S_ISDIR(s.st_mode);
|
return S_ISDIR(s.st_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
char* get_human_size(long size) {
|
char* get_human_size(long size)
|
||||||
|
{
|
||||||
//We should not get more than TB images
|
//We should not get more than TB images
|
||||||
char* unit[5] = {"B", "KB", "MB", "GB", "TB"};
|
char* unit[5] = { "B", "KB", "MB", "GB", "TB" };
|
||||||
//Index of the array containing the correct unit
|
//Index of the array containing the correct unit
|
||||||
double order = floor(log2(labs(size)) / 10);
|
double order = floor(log2(labs(size)) / 10);
|
||||||
//Alloc enough size for the final string
|
//Alloc enough size for the final string
|
||||||
char* final = (char*) malloc(((int) (floor(log10(labs(size))) + 4)) * sizeof(char));
|
char* final = (char*)malloc(((int)(floor(log10(labs(size))) + 4)) * sizeof(char));
|
||||||
|
|
||||||
//If the order exceeds 4, something is fishy
|
//If the order exceeds 4, something is fishy
|
||||||
if (order > 4) {
|
if (order > 4) {
|
||||||
fprintf(stdout, "[WARNING] Do you really have such a huge file?\n");
|
trigger_error(21, false);
|
||||||
order = 4;
|
order = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,13 +8,13 @@
|
||||||
#include "ccltypes.h"
|
#include "ccltypes.h"
|
||||||
|
|
||||||
#define APP_VERSION "0.9.1"
|
#define APP_VERSION "0.9.1"
|
||||||
#define BUILD 20160808
|
#define BUILD 20160922
|
||||||
|
|
||||||
int string_to_int(char* in_string);
|
int string_to_int(char* in_string);
|
||||||
void print_help();
|
void print_help();
|
||||||
int mkpath(const char *pathname, mode_t mode);
|
int mkpath(const char* pathname, mode_t mode);
|
||||||
enum image_type detect_image_type(char* path);
|
enum image_type detect_image_type(char* path);
|
||||||
int is_directory(const char *file_path);
|
int is_directory(const char* file_path);
|
||||||
void scan_folder(cclt_parameters* parameters, char* basedir, int recur);
|
void scan_folder(cclt_parameters* parameters, char* basedir, int recur);
|
||||||
char* get_human_size(long size);
|
char* get_human_size(long size);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue