Compression interface polished

Now uses libjpeg-turbo and keeps EXIFs
This commit is contained in:
Matteo Paonessa 2015-05-19 18:35:32 +02:00
parent 8c71d0d93b
commit 08500f84dc
6 changed files with 109 additions and 68 deletions

View File

@ -7,60 +7,45 @@
#include "compress.h"
#include "utils.h"
void cclt_compress(char* output_file, unsigned char* image_buffer, cclt_compress_parameters* pars)
{
struct jpeg_compress_struct cinfo;
//TODO Error handling
struct jpeg_error_mgr jerr;
FILE * outfile;
JSAMPROW row_pointer[1];
int row_stride;
void cclt_compress(char* output_file, unsigned char* image_buffer, cclt_compress_parameters* pars) {
FILE* fp;
tjhandle tjCompressHandle;
unsigned char* output_buffer;
int status;
unsigned long output_size = 0;
if ((outfile = fopen(output_file, "wb")) == NULL) {
fprintf(stderr, "can't open %s\n", output_file);
exit(1);
fp = fopen(output_file, "wb");
//Check for errors
//TODO Use UNIX error messages
if (fp == NULL) {
printf("INPUT: Failed to open output \"%s\"\n", output_file);
return;
}
cinfo.err = jpeg_std_error(&jerr);
output_buffer = NULL;
tjCompressHandle = tjInitCompress();
jpeg_create_compress(&cinfo);
jpeg_stdio_dest(&cinfo, outfile);
cinfo.image_width = pars->width;
cinfo.image_height = pars->height;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
jpeg_set_defaults(&cinfo);
cinfo.dct_method = pars->dct_method;
cinfo.optimize_coding = TRUE;
cinfo.smoothing_factor = pars->smoothing_factor;
jpeg_set_quality(&cinfo, pars->quality, TRUE);
jpeg_set_colorspace(&cinfo, JCS_RGB);
status = tjCompress2(tjCompressHandle,
image_buffer,
pars->width,
0,
pars->height,
pars->color_space,
&output_buffer,
&output_size,
pars->subsample,
pars->quality,
pars->dct_method);
fwrite(output_buffer, 1, output_size, fp);
jpeg_start_compress(&cinfo, TRUE);
row_stride = pars->width * 3;
while (cinfo.next_scanline < cinfo.image_height) {
//printf("%d%%\r", cinfo.next_scanline * 100 / cinfo.image_height);
row_pointer[0] = &image_buffer[cinfo.next_scanline * row_stride];
(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
//printf("%d%%\n", cinfo.next_scanline * 100 / cinfo.image_height);
jpeg_finish_compress(&cinfo);
fclose(outfile);
jpeg_destroy_compress(&cinfo);
fclose(fp);
tjDestroy(tjCompressHandle);
tjFree(output_buffer);
}
@ -85,7 +70,7 @@ unsigned char* cclt_decompress(char* fileName, cclt_compress_parameters* pars) {
int destWidth = fileWidth;
int destHeight = fileHeight;
pars->color_space = jpegSubsamp;
pars->subsample = jpegSubsamp;
@ -99,9 +84,11 @@ unsigned char* cclt_decompress(char* fileName, cclt_compress_parameters* pars) {
destWidth,
0,
destHeight,
TJPF_RGB,
pars->color_space,
TJFLAG_ACCURATEDCT);
tjDestroy(tjDecompressHandle);
pars->width = destWidth;
pars->height = destHeight;

View File

@ -2,11 +2,45 @@
#include <stdio.h>
#include <jpeglib.h>
#include <stdlib.h>
#include <string.h>
#include "lossless.h"
#include "utils.h"
int cclt_optimize(char* input_file, char* output_file, int exif_flag) {
struct jpeg_decompress_struct cclt_get_markers(char* input) {
FILE* fp;
struct jpeg_decompress_struct einfo;
struct jpeg_error_mgr eerr;
einfo.err = jpeg_std_error(&eerr);
jpeg_create_decompress(&einfo);
//Open the input file
fp = fopen(input, "r");
//Check for errors
//TODO Use UNIX error messages
if (fp == NULL) {
printf("INPUT: Failed to open exif file \"%s\"\n", input);
exit(-13);
}
//Create the IO istance for the input file
jpeg_stdio_src(&einfo, fp);
//Save EXIF info
for (int m = 0; m < 16; m++) {
jpeg_save_markers(&einfo, JPEG_APP0 + m, 0xFFFF);
}
jpeg_read_header(&einfo, TRUE);
fclose(fp);
return einfo;
}
int cclt_optimize(char* input_file, char* output_file, int exif_flag, char* exif_src) {
//File pointer for both input and output
FILE* fp;
@ -14,7 +48,7 @@ int cclt_optimize(char* input_file, char* output_file, int exif_flag) {
struct jpeg_decompress_struct srcinfo;
struct jpeg_compress_struct dstinfo;
//Error Handling
//Error handling
struct jpeg_error_mgr jsrcerr, jdsterr;
//Input/Output array coefficents
@ -74,21 +108,28 @@ int cclt_optimize(char* input_file, char* output_file, int exif_flag) {
//CRITICAL - This is the optimization step
dstinfo.optimize_coding = TRUE;
//Progressive
jpeg_simple_progression(&dstinfo);
//Set the output file parameters
jpeg_stdio_dest(&dstinfo, fp);
//Actually write the coefficents
jpeg_write_coefficients(&dstinfo, dst_coef_arrays);
//Write EXIF
if (exif_flag == 1) {
if (strcmp(input_file, exif_src) == 0) {
jcopy_markers_execute(&srcinfo, &dstinfo);
} else {
//For standard compression EXIF data
struct jpeg_decompress_struct einfo = cclt_get_markers(exif_src);
jcopy_markers_execute(&einfo, &dstinfo);
jpeg_destroy_decompress(&einfo);
}
}
//Free memory and finish
//Finish and free
jpeg_finish_compress(&dstinfo);
jpeg_destroy_compress(&dstinfo);
(void) jpeg_finish_decompress(&srcinfo);

View File

@ -1,6 +1,7 @@
#ifndef CCLT_LOSSLESS
#define CCLT_LOSSLESS
int cclt_optimize(char* input_file, char* output_file, int exif_flag);
int cclt_optimize(char* input_file, char* output_file, int exif_flag, char* exif_src);
struct jpeg_decompress_struct cclt_get_markers(char* input);
#endif

View File

@ -7,13 +7,14 @@
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <libexif/exif-data.h>
#include "lossless.h"
#include "compress.h"
#include "utils.h"
/* PARAMETERS:
-q quality
-q quality v
-e exif v
-o output folder v
-v version v
@ -123,12 +124,12 @@ int main (int argc, char *argv[]) {
//Lossless optmization requested
if (pars.lossless != 0) {
cclt_optimize(pars.input_files[i], output_filename, pars.exif_copy);
cclt_optimize(pars.input_files[i], output_filename, pars.exif_copy, pars.input_files[i]);
} else {
//TODO Standard compression requested
unsigned char* buffer = cclt_decompress(pars.input_files[i], &pars);
cclt_compress(output_filename, buffer, &pars);
//unsigned char* buffer = cclt_decompress(pars.input_files[i], &pars);
//cclt_compress(output_filename, buffer, &pars);
cclt_compress_routine(pars.input_files[i], output_filename, &pars);
}
//Get output stats

View File

@ -5,6 +5,7 @@
#include <setjmp.h>
#include <stdio.h>
#include <jpeglib.h>
#include <turbojpeg.h>
#include <string.h>
#include <sys/stat.h>
#include <getopt.h>
@ -12,6 +13,8 @@
#include "utils.h"
#include "compress.h"
#include "lossless.h"
cclt_compress_parameters initialize_compression_parameters() {
cclt_compress_parameters par;
@ -19,10 +22,9 @@ cclt_compress_parameters initialize_compression_parameters() {
par.quality = 0;
par.width = 0;
par.height = 0;
par.smoothing_factor = 100;
par.scaling_factor = 100;
par.color_space = JCS_RGB;
par.dct_method = JDCT_ISLOW;
par.color_space = TJPF_RGB;
par.dct_method = TJFLAG_FASTDCT;
par.output_folder = NULL;
par.exif_copy = 0;
par.lossless = 0;
@ -199,3 +201,10 @@ cclt_compress_parameters parse_arguments(int argc, char* argv[]) {
return parameters;
}
void cclt_compress_routine(char* input, char* output, cclt_compress_parameters* pars) {
cclt_compress(output, cclt_decompress(input, pars), pars);
cclt_optimize(output, output, pars->exif_copy, input);
}

View File

@ -2,6 +2,7 @@
#define CCLT_UTILS
#include <jpeglib.h>
#include <turbojpeg.h>
#define APP_VERSION "1.9.9 BETA"
#define BUILD 20150515
@ -10,15 +11,15 @@ typedef struct cclt_compress_parameters {
int quality;
int width;
int height;
int smoothing_factor;
int scaling_factor;
char* output_folder;
J_COLOR_SPACE color_space;
J_DCT_METHOD dct_method;
int color_space;
int dct_method;
int exif_copy;
int lossless;
char** input_files;
int input_files_count;
enum TJSAMP subsample;
} cclt_compress_parameters;
cclt_compress_parameters initialize_compression_parameters();
@ -30,5 +31,6 @@ char* get_filename_with_extension(char* full_path);
void jcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo);
int mkpath(const char *pathname, mode_t mode);
cclt_compress_parameters parse_arguments(int argc, char* argv[]);
void cclt_compress_routine(char* input, char* output,cclt_compress_parameters* pars);
#endif