Example and cleanup

This commit is contained in:
Matteo Paonessa 2024-10-11 15:17:51 +02:00
parent 0c7203a7e6
commit 31a1ca6f8b
8 changed files with 76 additions and 182 deletions

View File

@ -4,6 +4,7 @@
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" /> <sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/examples" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" /> <excludeFolder url="file://$MODULE_DIR$/target" />
<excludeFolder url="file://$MODULE_DIR$/dssim/target" /> <excludeFolder url="file://$MODULE_DIR$/dssim/target" />
</content> </content>

View File

@ -47,10 +47,6 @@ kamadak-exif = "0.5"
[dev-dependencies] [dev-dependencies]
dssim = { version = "3.3", default-features = false, features = ["no-macos-vimage"] } dssim = { version = "3.3", default-features = false, features = ["no-macos-vimage"] }
[[bin]]
name = "main"
path = "src/main.rs"
[lib] [lib]
name = "caesium" name = "caesium"
path = "src/lib.rs" path = "src/lib.rs"

185
README.md
View File

@ -7,155 +7,35 @@ Rust, with a C interface.
> starting from v0.6.0 the library is written in Rust and no longer in C. There's a C interface, but it's not backward > starting from v0.6.0 the library is written in Rust and no longer in C. There's a C interface, but it's not backward
> compatible with the <0.6.0. > compatible with the <0.6.0.
## Usage in Rust ## Usage example
Libcaesium exposes two functions, auto-detecting the input file type Libcaesium exposes two functions, auto-detecting the input file type
### Based on quality values
```Rust ```Rust
pub fn compress( use caesium::parameters::CSParameters;
input_path: String, use caesium::compress;
output_path: String,
parameters: &CSParameters let mut parameters = CSParameters::new();
) -> Result<(), Box<dyn Error>> parameters.keep_metadata = true;
parameters.jpeg.quality = 60;
let success = compress(input, output, &parameters).is_ok();
``` ```
#### Parameters ## Compilation
- `input_path` - input file path (full filename) Compilation is available for all supported platforms: Windows, macOS and Linux.
- `output_path` - output file path (full filename)
- `parameters` - options struct, containing compression parameters (see below)
### Based on output size > [!NOTE]
> if you don't use the `--release` flag, the PNG optimizations can take a very long time to complete, especially
> using the zopfli algorithm.
>
```Rust ```bash
pub fn compress_to_size( cargo build --release
input_path: String,
output_path: String,
parameters: &CSParameters,
max_output_size: usize,
) -> Result<(), Box<dyn Error>>
``` ```
#### Parameters The result will be a dynamic library usable by external applications through its C interface.
- `input_path` - input file path (full filename)
- `output_path` - output file path (full filename)
- `parameters` - options struct, containing compression parameters (see below)
- `max_output_size` - the maximum output size, in bytes
This function will attempt to compress the given file *below* the desired size. It will never exceed it. The function
will start looping until the best size under the desired is achieved. The function has a 2% tolerance for the output
size.
All quality value set to the parameters will be ignored and overwritten during the compression.
NOTE: The output folder where the file is compressed **must** exist.
### Compression options
Libcaesium supports a few compression parameters for each file it supports.
They are defined into a top level struct containing each supported file parameters, as follows:
```Rust
pub struct CSParameters {
pub jpeg: jpeg::Parameters,
pub png: png::Parameters,
pub gif: gif::Parameters,
pub webp: webp::Parameters,
pub tiff: tiff::Parameters,
pub keep_metadata: bool,
pub optimize: bool,
pub width: u32,
pub height: u32,
}
```
Each file type has its own options, but the last two are generic:
- `keep_metadata`: will keep metadata information for any supported type. JPEG and PNG supported. Default `false`.
- `optimize`: forces optimization, when available. With this option enabled the compression will be lossless. JPEG, PNG
and WebP supported. Default `false`.
- `width`: Resizes the image to the given width. If this value is `0` and the height value is also `0`, no resizing will
be done. If this is `0` and height is `> 0`, the image will be scaled based on height keeping the aspect ratio.
Default `0`.
- `height`: Resizes the image to the given height. If this value is `0` and the width value is also `0`, no resizing
will be done. If this is `0` and width is `> 0`, the image will be scaled based on width keeping the aspect ratio.
Default `0`.
#### jpeg
```Rust
pub struct Parameters {
pub quality: u32,
pub chroma_subsampling: jpeg::ChromaSubsampling,
pub progressive: bool
}
```
- `quality`: in a range from 0 to 100, the quality of the resulting image. Default `80`.
- `chroma_subsampling`: [chroma subsampling](https://en.wikipedia.org/wiki/Chroma_subsampling) to apply during
compression. Default `Auto`.
- `progressive`: outputs a progressive image (recommended). Set to `false` for baseline. Default `true`.
#### png
```Rust
pub struct Parameters {
pub quality: u32,
pub force_zopfli: bool,
pub optimization_level: u32
}
```
- `quality`: in a range from 0 to 100, the quality of the resulting image. Default `80`.
- `force_zopfli`: if `optimization` is `true` and this option is also `true`, will use zopfli algorithm for compression,
resulting in a smaller image, but it may take minutes to finish the process. Default `false`.
- `optimization_level`: if `optimization` is `true` will set the level of oxipng optimization, from 0 to 6. Default `3`.
#### gif
GIF support is experimental, has many know issues and does not support optimization. Expect bugs (especially on
Windows).
```Rust
pub struct Parameters {
pub quality: u32,
}
```
- `quality`: in a range from 0 to 100, the quality of the resulting image. If the optimization flag is `true`, the level
is set to `100`. Default: `80`.
#### webp
WebP's compression is tricky. The format is already well optimized and using the `optimize` flag will probably result in
a bigger image.
```Rust
pub struct Parameters {
pub quality: u32,
}
```
- `quality`: in a range from 0 to 100, the quality of the resulting image. If the optimization flag is `true`, this
option will be ignored. Default: `60`.
#### tiff
Supported TIFF compression is only lossless. The supported algorithms are: Lzw, Deflate, Packbits, Uncompressed.
```Rust
pub struct Parameters {
pub algorithm: TiffCompression,
pub deflate_level: TiffDeflateLevel,
}
```
- `algorithm`: supported algorithms are: Lzw, Deflate, Packbits, Uncompressed.
- `deflate_level`: can be one of `Fast`, `Balanced`, `Best`.
_________________
## Usage in C ## Usage in C
@ -249,38 +129,19 @@ pub struct CCSParameters {
``` ```
The option description is the same as the Rust counterpart. The option description is the same as the Rust counterpart.
Valid values for `jpeg_chroma_subsampling` are [444, 422, 420, 411]. Any other value will be ignored and will be used Valid values for `jpeg_chroma_subsampling` are `[444, 422, 420, 411]`. Any other value will be ignored and will be used
the default option. the default option.
Valid values for `tiff_compression` are [0 (Uncompressed), 1 (Lzw), 2 (Deflate), 3 (Packbits)]. Any other value will be Valid values for `tiff_compression` are `[0 (Uncompressed), 1 (Lzw), 2 (Deflate), 3 (Packbits)]`. Any other value will be
ignored and `0` will be used. ignored and `0` will be used.
Valid values for `tiff_deflate_level` are [1 (Fast), 6 (Balanced), 9 (Best)]. Any other value will be ignored and `Best` Valid values for `tiff_deflate_level` are `[1 (Fast), 6 (Balanced), 9 (Best)]`. Any other value will be ignored and `Best`
will be used. will be used.
## Download
Binaries not available. Please refer to the compilation section below.
## Compilation and Installation
Compilation is available for all supported platforms: Windows, macOS and Linux.
```
cargo build --release
```
Note: if you don't use the `--release` flag, the PNG optimizations can take a very long time to complete, especially
using the zopfli algorithm.
The result will be a dynamic library usable by external applications through its C interface.
## Compression vs Optimization ## Compression vs Optimization
JPEG is a lossy format: that means you will always lose some information after each compression. So, compressing a file JPEG is a lossy format: that means you will always lose some information after each compression. So, compressing a file
with with 100 quality for 10 times will result in an always different image, even though you can't really see the difference.
100 quality for 10 times will result in an always different image, even though you can't really see the difference.
Libcaesium also supports optimization, by setting the _quality_ to 0. This performs a lossless process, resulting in the Libcaesium also supports optimization, by setting the _quality_ to 0. This performs a lossless process, resulting in the
same image, same image, but with a smaller size (10-12% usually).
but with a smaller size (10-12% usually).
GIF optimization is possible, but currently not supported. GIF optimization is possible, but currently not supported.
WebP's optimization is also possible, but it will probably result in a bigger output file as it's well suited to WebP's optimization is also possible, but it will probably result in a bigger output file as it's well suited to
losslessly convert from PNG or JPEG. losslessly convert from PNG or JPEG.

View File

@ -9,7 +9,10 @@ fn main() -> ExitCode {
let input = args[1].clone(); let input = args[1].clone();
let output = args[2].clone(); let output = args[2].clone();
let parameters = CSParameters::new(); let mut parameters = CSParameters::new();
parameters.keep_metadata = true;
parameters.jpeg.quality = 60;
match compress(input, output, &parameters) { match compress(input, output, &parameters) {
Ok(_) => ExitCode::SUCCESS, Ok(_) => ExitCode::SUCCESS,
Err(e) => { Err(e) => {

22
examples/convert.rs Normal file
View File

@ -0,0 +1,22 @@
use caesium::parameters::CSParameters;
use caesium::convert;
use std::env;
use std::process::ExitCode;
fn main() -> ExitCode {
let args: Vec<String> = env::args().collect();
let input = args[1].clone();
let output = args[2].clone();
let mut parameters = CSParameters::new();
parameters.png.quality = 60;
match convert(input, output, &parameters, caesium::SupportedFileTypes::Png) {
Ok(_) => ExitCode::SUCCESS,
Err(e) => {
eprintln!("{}", e);
ExitCode::FAILURE
}
}
}

21
examples/size.rs Normal file
View File

@ -0,0 +1,21 @@
use caesium::compress_to_size;
use caesium::parameters::CSParameters;
use std::env;
use std::process::ExitCode;
fn main() -> ExitCode {
let args: Vec<String> = env::args().collect();
let input = args[1].clone();
let output = args[2].clone();
let mut parameters = CSParameters::new();
match compress_to_size(input, output, &mut parameters, 1000000, true) {
Ok(_) => ExitCode::SUCCESS,
Err(e) => {
eprintln!("{}", e);
ExitCode::FAILURE
}
}
}

View File

@ -381,13 +381,6 @@ fn validate_parameters(parameters: &CSParameters) -> error::Result<()> {
}); });
} }
if parameters.optimize && parameters.output_size > 0 {
return Err(CaesiumError {
message: "Cannot compress to desired size with lossless optimization".into(),
code: 10005,
});
}
Ok(()) Ok(())
} }

View File

@ -109,7 +109,6 @@ pub struct TiffParameters {
/// - `optimize`: Whether to use lossless compression /// - `optimize`: Whether to use lossless compression
/// - `width`: Width of the output image /// - `width`: Width of the output image
/// - `height`: Height of the output image /// - `height`: Height of the output image
/// - `output_size`: Desired output size of the compressed image
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct CSParameters { pub struct CSParameters {
pub jpeg: JpegParameters, pub jpeg: JpegParameters,
@ -120,8 +119,7 @@ pub struct CSParameters {
pub keep_metadata: bool, pub keep_metadata: bool,
pub optimize: bool, pub optimize: bool,
pub width: u32, pub width: u32,
pub height: u32, pub height: u32
pub output_size: u32,
} }
impl Default for CSParameters { impl Default for CSParameters {
fn default() -> Self { fn default() -> Self {
@ -162,7 +160,6 @@ fn initialize_parameters() -> CSParameters {
keep_metadata: false, keep_metadata: false,
optimize: false, optimize: false,
width: 0, width: 0,
height: 0, height: 0
output_size: 0,
} }
} }