Code style adjustments

This commit is contained in:
Matteo Paonessa 2016-12-15 21:37:44 +01:00
parent 9326392bb3
commit 0ac1a50f1e
8 changed files with 308 additions and 285 deletions

View File

@ -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(&parameters, argv[optind], parameters.recursive); scan_folder(&parameters, 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++;
} }
} }

View File

@ -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);
} }
} }

View File

@ -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);
} }
} }

View File

@ -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

View File

@ -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;
} }

View File

@ -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);
} }

View File

@ -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;
} }

View File

@ -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);