0.4.0
This commit is contained in:
parent
9fd0fa5f27
commit
45b794d498
|
@ -7,7 +7,7 @@ set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
|||
|
||||
# The version number.
|
||||
set(VERSION_MAJOR 0)
|
||||
set(VERSION_MINOR 3)
|
||||
set(VERSION_MINOR 4)
|
||||
set(VERSION_PATCH 0)
|
||||
|
||||
configure_file(
|
||||
|
|
13
README.md
13
README.md
|
@ -41,13 +41,15 @@ typedef struct cs_jpeg_pars
|
|||
int quality;
|
||||
bool exif_copy;
|
||||
int dct_method;
|
||||
double scale_factor;
|
||||
} cs_jpeg_pars;
|
||||
```
|
||||
The first 3 parameters matters, in term of compression, while the others will be set by the compressor/decompressor
|
||||
The first 4 parameters matters, in term of compression, while the others will be set by the compressor/decompressor
|
||||
during the compression progress and thus they will be overwritten.
|
||||
- **quality**: in a range from 0 to 100, the quality of the resulting image. **Note** that 0 means _optimization_ (see below). Default: 0.
|
||||
- **exif_copy**: set it to _true_ to copy EXIF tag info after compression. Default: false.
|
||||
- **dct_method**: one of the turbojpeg DCT flags. Default: TJFLAG_FASTDCT.
|
||||
- **scale_factor**: the image scaling factor, expressed as double precision number. Default: 1.0.
|
||||
|
||||
### PNG
|
||||
```C
|
||||
|
@ -59,15 +61,18 @@ typedef struct cs_png_pars
|
|||
bool lossy_8;
|
||||
bool transparent;
|
||||
int auto_filter_strategy;
|
||||
double scale_factor;
|
||||
} cs_png_pars;
|
||||
```
|
||||
Those are the zopflipng compression parameters.
|
||||
Those are the zopflipng compression parameters, except for the last one.
|
||||
- **iterations**: number of iterations (more means more compression). Default: 10.
|
||||
- **iteration_large**: number of iterations for large files. Default: 5.
|
||||
- **block_split_strategy**: filter strategy. Default: 4;
|
||||
- **lossy_8**: convert 16-bit per channel image to 8-bit per channel. Default: true.
|
||||
- **transparent**: remove colors behind alpha channel 0. Default: true.
|
||||
- **auto_filter_strategy**: legacy.
|
||||
- **scale_factor**: the image scaling factor, expressed as double precision number. Note that PNG cannot be upscaled. Default: 1.0.
|
||||
|
||||
|
||||
## Compilation and Installation
|
||||
Libcaesium uses cmake to build and install the library. Before compiling, be sure to have all the requisites.
|
||||
|
@ -121,3 +126,7 @@ JPEG is a lossy format: that means you will always lose some information after e
|
|||
Libcaesium also supports optimization, by setting the _quality_ to 0. This performs a lossless process, resulting in the same image,
|
||||
but with a smaller size (10-15% usually).
|
||||
PNG is lossless, so libcaesium will always perform optimization rather than compression.
|
||||
|
||||
## Resizing
|
||||
Resizing is partially supported. It is handy but it's almost completely out of the scope of this library.
|
||||
If you really feel the need to do it within libcaesium you can do so, but I advise you should opt for a different toolset for the best results.
|
|
@ -10,8 +10,8 @@ find_library(zopflipng zopflipng /usr/local/lib)
|
|||
find_library(jpeg jpeg /opt/mozjpeg/lib)
|
||||
find_library(turbojpeg turbojpeg /opt/mozjpeg/lib)
|
||||
|
||||
add_library(caesium SHARED caesium.c error.c utils.c png.c lodepng.c jpeg.c)
|
||||
add_library(caesium_static STATIC caesium.c error.c utils.c png.c lodepng.c jpeg.c)
|
||||
add_library(caesium SHARED caesium.c error.c utils.c png.c vendor/lodepng.c jpeg.c)
|
||||
add_library(caesium_static STATIC caesium.c error.c utils.c png.c vendor/lodepng.c jpeg.c)
|
||||
|
||||
set_target_properties(caesium_static PROPERTIES OUTPUT_NAME caesium)
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ bool cs_compress(const char *input_path, const char *output_path, cs_image_pars
|
|||
FILE *pInputFile;
|
||||
image_type type;
|
||||
bool result = false;
|
||||
int compression_step_result;
|
||||
|
||||
if ((pInputFile = fopen(input_path, "rb")) == NULL) {
|
||||
display_error(ERROR, 104);
|
||||
|
@ -25,10 +26,11 @@ bool cs_compress(const char *input_path, const char *output_path, cs_image_pars
|
|||
display_error(WARNING, 103);
|
||||
} else if (type == CS_JPEG) {
|
||||
if (options->jpeg.quality != 0) {
|
||||
result = cs_jpeg_compress(output_path, cs_jpeg_decompress(input_path, &options->jpeg), &options->jpeg);
|
||||
compression_step_result = cs_jpeg_compress(output_path, cs_jpeg_decompress(input_path, &options->jpeg), &options->jpeg);
|
||||
result = (bool) compression_step_result;
|
||||
//The output is now the new input for optimization
|
||||
if (result) {
|
||||
result = cs_jpeg_optimize(output_path, output_path, &options->jpeg, input_path);
|
||||
result = cs_jpeg_optimize(compression_step_result == 1 ? output_path : input_path, output_path, &options->jpeg, input_path);
|
||||
}
|
||||
} else {
|
||||
result = cs_jpeg_optimize(input_path, output_path, &options->jpeg, input_path);
|
||||
|
@ -45,16 +47,18 @@ void initialize_jpeg_parameters(cs_image_pars *options)
|
|||
options->jpeg.quality = 0;
|
||||
options->jpeg.exif_copy = false;
|
||||
options->jpeg.dct_method = 2048;
|
||||
options->jpeg.scale_factor = 1.0;
|
||||
}
|
||||
|
||||
void initialize_png_parameters(cs_image_pars *par)
|
||||
void initialize_png_parameters(cs_image_pars *options)
|
||||
{
|
||||
par->png.iterations = 2;
|
||||
par->png.iterations_large = 1;
|
||||
par->png.block_split_strategy = 0;
|
||||
par->png.lossy_8 = true;
|
||||
par->png.transparent = true;
|
||||
par->png.auto_filter_strategy = true;
|
||||
options->png.iterations = 2;
|
||||
options->png.iterations_large = 1;
|
||||
options->png.block_split_strategy = 0;
|
||||
options->png.lossy_8 = true;
|
||||
options->png.transparent = true;
|
||||
options->png.auto_filter_strategy = true;
|
||||
options->png.scale_factor = 1.0;
|
||||
}
|
||||
|
||||
cs_image_pars initialize_parameters()
|
||||
|
|
|
@ -13,6 +13,7 @@ typedef struct cs_jpeg_pars
|
|||
int quality;
|
||||
bool exif_copy;
|
||||
int dct_method;
|
||||
double scale_factor;
|
||||
/*
|
||||
* Parameters you have no reason to set as they will be
|
||||
* overwritten during the process
|
||||
|
@ -31,6 +32,7 @@ typedef struct cs_png_pars
|
|||
bool lossy_8;
|
||||
bool transparent;
|
||||
int auto_filter_strategy;
|
||||
double scale_factor;
|
||||
} cs_png_pars;
|
||||
|
||||
typedef struct cs_image_pars
|
||||
|
|
|
@ -40,7 +40,9 @@ const char *get_error_message(int code)
|
|||
case 207:
|
||||
return "Compressor failed";
|
||||
case 208:
|
||||
return "Compressor failed";
|
||||
return "Decompressor failed";
|
||||
case 209:
|
||||
return "CMYK images are not fully supported and can only be optimized.";
|
||||
|
||||
//PNG related errors
|
||||
case 300:
|
||||
|
@ -49,6 +51,10 @@ const char *get_error_message(int code)
|
|||
return "Error while optimizing PNG.";
|
||||
case 303:
|
||||
return "Error while writing output PNG file.";
|
||||
case 304:
|
||||
return "Error while resizing PNG file.";
|
||||
case 305:
|
||||
return "PNG scaling factor must be a number greater than 0 and equal or minor to 1.";
|
||||
|
||||
default:
|
||||
return "Unrecognized error.";
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <string.h>
|
||||
#include <turbojpeg.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "jpeg.h"
|
||||
#include "error.h"
|
||||
|
@ -127,8 +128,11 @@ bool cs_jpeg_optimize(const char *input_file, const char *output_file, cs_jpeg_p
|
|||
return true;
|
||||
}
|
||||
|
||||
bool cs_jpeg_compress(const char *output_file, unsigned char *image_buffer, cs_jpeg_pars *options)
|
||||
int cs_jpeg_compress(const char *output_file, unsigned char *image_buffer, cs_jpeg_pars *options)
|
||||
{
|
||||
if (image_buffer == 0) {
|
||||
return 2;
|
||||
}
|
||||
FILE *fp;
|
||||
tjhandle tjCompressHandle;
|
||||
unsigned char *output_buffer;
|
||||
|
@ -165,7 +169,7 @@ bool cs_jpeg_compress(const char *output_file, unsigned char *image_buffer, cs_j
|
|||
tjFree(output_buffer);
|
||||
tjFree(image_buffer);
|
||||
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned char *cs_jpeg_decompress(const char *fileName, cs_jpeg_pars *options)
|
||||
|
@ -195,13 +199,18 @@ unsigned char *cs_jpeg_decompress(const char *fileName, cs_jpeg_pars *options)
|
|||
tjDecompressHeader3(tjDecompressHandle, sourceJpegBuffer, (unsigned long) sourceJpegBufferSize, &fileWidth, &fileHeight,
|
||||
&jpegSubsamp, &colorSpace);
|
||||
|
||||
options->width = fileWidth;
|
||||
options->height = fileHeight;
|
||||
if (colorSpace == 4) { //CMYK
|
||||
display_error(WARNING, 209);
|
||||
return 0;
|
||||
}
|
||||
|
||||
options->width = (int) round(fileWidth * options->scale_factor);
|
||||
options->height = (int) round(fileHeight * options->scale_factor);
|
||||
|
||||
options->subsample = (enum TJSAMP) jpegSubsamp;
|
||||
options->color_space = colorSpace;
|
||||
|
||||
unsigned char *temp = tjAlloc(options->width * options->height * tjPixelSize[options->color_space]);
|
||||
unsigned char *temp = tjAlloc(options->width * options->height * tjPixelSize[colorSpace]);
|
||||
|
||||
result = tjDecompress2(tjDecompressHandle,
|
||||
sourceJpegBuffer,
|
||||
|
@ -210,7 +219,7 @@ unsigned char *cs_jpeg_decompress(const char *fileName, cs_jpeg_pars *options)
|
|||
options->width,
|
||||
0,
|
||||
options->height,
|
||||
options->color_space,
|
||||
colorSpace,
|
||||
options->dct_method);
|
||||
if (result == -1) {
|
||||
display_error(ERROR, 208);
|
||||
|
|
|
@ -9,7 +9,7 @@ bool cs_jpeg_optimize(const char *input_file, const char *output_file, cs_jpeg_p
|
|||
|
||||
struct jpeg_decompress_struct cs_get_markers(const char *input);
|
||||
|
||||
bool cs_jpeg_compress(const char *output_file, unsigned char *image_buffer, cs_jpeg_pars *options);
|
||||
int cs_jpeg_compress(const char *output_file, unsigned char *image_buffer, cs_jpeg_pars *options);
|
||||
|
||||
unsigned char *cs_jpeg_decompress(const char *fileName, cs_jpeg_pars *options);
|
||||
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
//
|
||||
// Created by Matteo Paonessa on 08/11/16.
|
||||
//
|
||||
#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
|
||||
#define STBIW_ASSERT(x)
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <zopflipng/zopflipng_lib.h>
|
||||
|
||||
#include "vendor/stb_image.h"
|
||||
#include "vendor/stb_image_write.h"
|
||||
#include "vendor/stb_image_resize.h"
|
||||
#include "png.h"
|
||||
#include "lodepng.h"
|
||||
#include "vendor/lodepng.h"
|
||||
#include "error.h"
|
||||
|
||||
bool cs_png_optimize(const char *input, const char *output, cs_png_pars *options)
|
||||
|
@ -15,6 +20,17 @@ bool cs_png_optimize(const char *input, const char *output, cs_png_pars *options
|
|||
CZopfliPNGOptions png_options;
|
||||
int error_code = 0;
|
||||
|
||||
if (options->scale_factor > 0.0 && options->scale_factor < 1.0) {
|
||||
result = cs_png_resize(input, output, options->scale_factor);
|
||||
if (!result) {
|
||||
display_error(ERROR, 304);
|
||||
return result;
|
||||
}
|
||||
} else if (options->scale_factor != 1.0) {
|
||||
display_error(ERROR, 305);
|
||||
return false;
|
||||
}
|
||||
|
||||
CZopfliPNGSetDefaults(&png_options);
|
||||
|
||||
unsigned char *orig_buffer;
|
||||
|
@ -32,17 +48,19 @@ bool cs_png_optimize(const char *input, const char *output, cs_png_pars *options
|
|||
|
||||
png_options.auto_filter_strategy = options->auto_filter_strategy;
|
||||
|
||||
if (lodepng_load_file(&orig_buffer, &orig_buffer_size, input) != 0) {
|
||||
if (lodepng_load_file(&orig_buffer, &orig_buffer_size, options->scale_factor == 1 ? input : output) != 0) {
|
||||
error_code = 300;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (CZopfliPNGOptimize(orig_buffer,
|
||||
int code = CZopfliPNGOptimize(orig_buffer,
|
||||
orig_buffer_size,
|
||||
&png_options,
|
||||
0,
|
||||
&resultpng,
|
||||
&resultpng_size) != 0) {
|
||||
&resultpng_size);
|
||||
|
||||
if (code != 0) {
|
||||
error_code = 301;
|
||||
goto cleanup;
|
||||
}
|
||||
|
@ -62,3 +80,33 @@ bool cs_png_optimize(const char *input, const char *output, cs_png_pars *options
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool cs_png_resize(const char *input, const char *output, double factor)
|
||||
{
|
||||
unsigned char *input_pixels;
|
||||
unsigned char *output_pixels;
|
||||
int w, h;
|
||||
int n;
|
||||
int out_w, out_h;
|
||||
int result;
|
||||
|
||||
input_pixels = stbi_load(input, &w, &h, &n, 0);
|
||||
if (input_pixels == 0) {
|
||||
return false;
|
||||
}
|
||||
out_w = (int) round(w * factor);
|
||||
out_h = (int) round(h * factor);
|
||||
|
||||
output_pixels = (unsigned char *) malloc(out_w * out_h * n);
|
||||
result = stbir_resize_uint8(input_pixels, w, h, 0, output_pixels, out_w, out_h, 0, n);
|
||||
if (!result) {
|
||||
free(output_pixels);
|
||||
return false;
|
||||
}
|
||||
result = stbi_write_png(output, out_w, out_h, n, output_pixels, 0);
|
||||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
//
|
||||
// Created by Matteo Paonessa on 08/11/16.
|
||||
//
|
||||
|
||||
#ifndef LIBCAESIUM_PNG_H
|
||||
#define LIBCAESIUM_PNG_H
|
||||
|
||||
|
@ -9,4 +5,6 @@
|
|||
|
||||
bool cs_png_optimize(const char *input, const char *output, cs_png_pars *options);
|
||||
|
||||
bool cs_png_resize(const char *input, const char *output, double factor);
|
||||
|
||||
#endif //LIBCAESIUM_PNG_H
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue