Changed return type of C interface
This commit is contained in:
parent
5c6da6f755
commit
af3556d19d
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="MarkdownSettings">
|
||||||
|
<option name="areInjectionsEnabled" value="false" />
|
||||||
|
</component>
|
||||||
|
</project>
|
10
Cargo.toml
10
Cargo.toml
|
@ -1,8 +1,8 @@
|
||||||
[package]
|
[package]
|
||||||
name = "libcaesium"
|
name = "libcaesium"
|
||||||
version = "0.7.0"
|
version = "0.8.0"
|
||||||
authors = ["Matteo Paonessa <matteo.paonessa@gmail.com>"]
|
authors = ["Matteo Paonessa <matteo.paonessa@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
categories = ["multimedia::images"]
|
categories = ["multimedia::images"]
|
||||||
keywords = [
|
keywords = [
|
||||||
"compression",
|
"compression",
|
||||||
|
@ -24,17 +24,17 @@ license = "Apache-2.0"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
mozjpeg-sys = "1.0.1"
|
mozjpeg-sys = "1.0.1"
|
||||||
oxipng = "5.0.1"
|
oxipng = "5.0.1"
|
||||||
libc = "0.2.76"
|
libc = "0.2.119"
|
||||||
gifsicle = "1.92.5"
|
gifsicle = "1.92.5"
|
||||||
webp = "0.2.1"
|
webp = "0.2.1"
|
||||||
infer = "0.6.0"
|
infer = "0.7.0"
|
||||||
image = { version = "0.24", default-features = false, features = ["jpeg", "png", "webp", "gif"] }
|
image = { version = "0.24", default-features = false, features = ["jpeg", "png", "webp", "gif"] }
|
||||||
img-parts = "0.2.3"
|
img-parts = "0.2.3"
|
||||||
bytes = "1.1.0"
|
bytes = "1.1.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
dssim = "3.2.0"
|
dssim = "3.2.0"
|
||||||
kamadak-exif = "0.5.0"
|
kamadak-exif = "0.5.4"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "caesium"
|
name = "caesium"
|
||||||
|
|
21
README.md
21
README.md
|
@ -17,7 +17,7 @@ pub fn compress(
|
||||||
- `output_path` - output file path (full filename)
|
- `output_path` - output file path (full filename)
|
||||||
- `parameters` - options struct, containing compression parameters (see below)
|
- `parameters` - options struct, containing compression parameters (see below)
|
||||||
|
|
||||||
The output folder where the file is compressed **must** exist.
|
NOTE: The output folder where the file is compressed **must** exist.
|
||||||
### Compression options
|
### Compression options
|
||||||
Libcaesium supports a few compression parameters for each file it supports.
|
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:
|
They are defined into a top level struct containing each supported file parameters, as follows:
|
||||||
|
@ -57,7 +57,7 @@ pub struct Parameters {
|
||||||
```
|
```
|
||||||
- `oxipng`: oxipng options. Should be left as default unless you want to do something advanced. Refer to [oxipng](https://github.com/shssoichiro/oxipng) for documentation.
|
- `oxipng`: oxipng options. Should be left as default unless you want to do something advanced. Refer to [oxipng](https://github.com/shssoichiro/oxipng) for documentation.
|
||||||
- `level`: level of optimization, from 1 to 7. Increasing the level will result in a smaller file, at the cost of computation time. If the optimization flag is `true`, the level is set to `6`. Default: `3`.
|
- `level`: level of optimization, from 1 to 7. Increasing the level will result in a smaller file, at the cost of computation time. If the optimization flag is `true`, the level is set to `6`. Default: `3`.
|
||||||
- `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`.
|
- `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`.
|
||||||
|
|
||||||
#### gif
|
#### gif
|
||||||
GIF support is experimental, has many know issues and does not support optimization. Expect bugs (especially on Windows).
|
GIF support is experimental, has many know issues and does not support optimization. Expect bugs (especially on Windows).
|
||||||
|
@ -69,7 +69,7 @@ pub struct Parameters {
|
||||||
- `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`.
|
- `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
|
||||||
WebP compression is tricky. The format is already well optimized and using the `optimize` flag will probably result in a bigger image.
|
WebP's compression is tricky. The format is already well optimized and using the `optimize` flag will probably result in a bigger image.
|
||||||
```Rust
|
```Rust
|
||||||
pub struct Parameters {
|
pub struct Parameters {
|
||||||
pub quality: u32,
|
pub quality: u32,
|
||||||
|
@ -84,14 +84,23 @@ pub extern fn c_compress(
|
||||||
input_path: *const c_char,
|
input_path: *const c_char,
|
||||||
output_path: *const c_char,
|
output_path: *const c_char,
|
||||||
params: CCSParameters
|
params: CCSParameters
|
||||||
) -> bool
|
) -> CCSResult
|
||||||
```
|
```
|
||||||
#### Parameters
|
#### Parameters
|
||||||
- `input_path` - input file path (full filename)
|
- `input_path` - input file path (full filename)
|
||||||
- `output_path` - output file path (full filename)
|
- `output_path` - output file path (full filename)
|
||||||
- `parameters` - options struct, containing compression parameters (see below)
|
- `parameters` - options struct, containing compression parameters (see below)
|
||||||
#### Return
|
#### Return
|
||||||
`true` if all goes well, `false` otherwise.
|
A `CCSResult` struct
|
||||||
|
```Rust
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct CCSResult {
|
||||||
|
pub success: bool,
|
||||||
|
pub error_message: *const c_char,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
If `success` is `true` the compression process ended successfully and `error_message` will be empty.
|
||||||
|
On failure, the `error_message` will be filled with a string containing a brief explanation of the error.
|
||||||
|
|
||||||
### Compression options
|
### Compression options
|
||||||
The C options struct is slightly different from the Rust one:
|
The C options struct is slightly different from the Rust one:
|
||||||
|
@ -131,4 +140,4 @@ Libcaesium also supports optimization, by setting the _quality_ to 0. This perfo
|
||||||
but with a smaller size (10-12% usually).
|
but with a smaller size (10-12% usually).
|
||||||
PNG is lossless, so libcaesium will always perform optimization rather than compression.
|
PNG is lossless, so libcaesium will always perform optimization rather than compression.
|
||||||
GIF optimization is possible, but currently not supported.
|
GIF optimization is possible, but currently not supported.
|
||||||
WebP 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.s
|
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.s
|
||||||
|
|
10
src/jpeg.rs
10
src/jpeg.rs
|
@ -16,6 +16,7 @@ pub fn compress(input_path: String, output_path: String, parameters: CSParameter
|
||||||
{
|
{
|
||||||
let mut in_file = fs::read(input_path)?;
|
let mut in_file = fs::read(input_path)?;
|
||||||
|
|
||||||
|
|
||||||
if parameters.width > 0 || parameters.height > 0 {
|
if parameters.width > 0 || parameters.height > 0 {
|
||||||
if parameters.keep_metadata {
|
if parameters.keep_metadata {
|
||||||
let metadata = extract_metadata(in_file.clone());
|
let metadata = extract_metadata(in_file.clone());
|
||||||
|
@ -27,12 +28,11 @@ pub fn compress(input_path: String, output_path: String, parameters: CSParameter
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let compression_buffer: (*mut u8, u64);
|
let compression_buffer: (*mut u8, u64) = if parameters.optimize {
|
||||||
if parameters.optimize {
|
lossless(in_file, parameters)?
|
||||||
compression_buffer = lossless(in_file, parameters)?;
|
|
||||||
} else {
|
} else {
|
||||||
compression_buffer = lossy(in_file, parameters)?;
|
lossy(in_file, parameters)?
|
||||||
}
|
};
|
||||||
let mut output_file_buffer = File::create(output_path)?;
|
let mut output_file_buffer = File::create(output_path)?;
|
||||||
output_file_buffer.write_all(std::slice::from_raw_parts(compression_buffer.0, compression_buffer.1 as usize))?;
|
output_file_buffer.write_all(std::slice::from_raw_parts(compression_buffer.0, compression_buffer.1 as usize))?;
|
||||||
}
|
}
|
||||||
|
|
72
src/lib.rs
72
src/lib.rs
|
@ -7,7 +7,7 @@ mod resize;
|
||||||
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use crate::utils::get_filetype;
|
use crate::utils::get_filetype;
|
||||||
use std::ffi::CStr;
|
use std::ffi::{CStr, CString};
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -23,6 +23,12 @@ pub struct CCSParameters {
|
||||||
pub height: u32,
|
pub height: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct CCSResult {
|
||||||
|
pub success: bool,
|
||||||
|
pub error_message: *const c_char,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct CSParameters {
|
pub struct CSParameters {
|
||||||
pub jpeg: jpeg::Parameters,
|
pub jpeg: jpeg::Parameters,
|
||||||
pub png: png::Parameters,
|
pub png: png::Parameters,
|
||||||
|
@ -68,8 +74,9 @@ pub fn initialize_parameters() -> CSParameters
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[allow(clippy::missing_safety_doc)]
|
#[allow(clippy::missing_safety_doc)]
|
||||||
pub unsafe extern fn c_compress(input_path: *const c_char, output_path: *const c_char, params: CCSParameters) -> bool {
|
pub unsafe extern fn c_compress(input_path: *const c_char, output_path: *const c_char, params: CCSParameters) -> CCSResult {
|
||||||
let mut parameters = initialize_parameters();
|
let mut parameters = initialize_parameters();
|
||||||
|
|
||||||
parameters.jpeg.quality = params.jpeg_quality;
|
parameters.jpeg.quality = params.jpeg_quality;
|
||||||
parameters.png.level = params.png_level;
|
parameters.png.level = params.png_level;
|
||||||
parameters.optimize = params.optimize;
|
parameters.optimize = params.optimize;
|
||||||
|
@ -80,10 +87,29 @@ pub unsafe extern fn c_compress(input_path: *const c_char, output_path: *const c
|
||||||
parameters.width = params.width;
|
parameters.width = params.width;
|
||||||
parameters.height = params.height;
|
parameters.height = params.height;
|
||||||
|
|
||||||
let x = compress(CStr::from_ptr(input_path).to_str().unwrap().to_string(),
|
let mut error_message = CString::new("").unwrap();
|
||||||
CStr::from_ptr(output_path).to_str().unwrap().to_string(),
|
|
||||||
parameters).is_ok();
|
match compress(CStr::from_ptr(input_path).to_str().unwrap().to_string(),
|
||||||
x
|
CStr::from_ptr(output_path).to_str().unwrap().to_string(),
|
||||||
|
parameters) {
|
||||||
|
Ok(_) => {
|
||||||
|
let em_pointer = error_message.as_ptr();
|
||||||
|
std::mem::forget(error_message);
|
||||||
|
CCSResult {
|
||||||
|
success: true,
|
||||||
|
error_message: em_pointer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error_message = CString::new(e.to_string()).unwrap();
|
||||||
|
let em_pointer = error_message.as_ptr();
|
||||||
|
std::mem::forget(error_message);
|
||||||
|
CCSResult {
|
||||||
|
success: false,
|
||||||
|
error_message: em_pointer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compress(input_path: String, output_path: String, parameters: CSParameters) -> Result<(), Box<dyn Error>> {
|
pub fn compress(input_path: String, output_path: String, parameters: CSParameters) -> Result<(), Box<dyn Error>> {
|
||||||
|
@ -92,43 +118,21 @@ pub fn compress(input_path: String, output_path: String, parameters: CSParameter
|
||||||
|
|
||||||
match file_type {
|
match file_type {
|
||||||
utils::SupportedFileTypes::Jpeg => {
|
utils::SupportedFileTypes::Jpeg => {
|
||||||
return match jpeg::compress(input_path, output_path, parameters) {
|
jpeg::compress(input_path, output_path, parameters)?;
|
||||||
Ok(_) => Ok(()),
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!("JPEG compression error: {}", e.to_string());
|
|
||||||
Err(e.into())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
utils::SupportedFileTypes::Png => {
|
utils::SupportedFileTypes::Png => {
|
||||||
return match png::compress(input_path, output_path, parameters) {
|
png::compress(input_path, output_path, parameters)?;
|
||||||
Ok(_) => Ok(()),
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!("PNG compression error: {}", e.to_string());
|
|
||||||
Err(e.into())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
utils::SupportedFileTypes::Gif => {
|
utils::SupportedFileTypes::Gif => {
|
||||||
return match gif::compress(input_path, output_path, parameters) {
|
gif::compress(input_path, output_path, parameters)?;
|
||||||
Ok(_) => Ok(()),
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!("GIF compression error: {}", e.to_string());
|
|
||||||
Err(e.into())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
utils::SupportedFileTypes::WebP => {
|
utils::SupportedFileTypes::WebP => {
|
||||||
return match webp::compress(input_path, output_path, parameters) {
|
webp::compress(input_path, output_path, parameters)?;
|
||||||
Ok(_) => Ok(()),
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!("WebP compression error: {}", e.to_string());
|
|
||||||
Err(e.into())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
_ => return Err("Unknown file type".into())
|
_ => return Err("Unknown file type".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_parameters(parameters: &CSParameters) -> Result<(), Box<dyn Error>> {
|
fn validate_parameters(parameters: &CSParameters) -> Result<(), Box<dyn Error>> {
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
use caesium;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn unknown_file_type() {
|
fn unknown_file_type() {
|
||||||
let output = "tests/samples/output/should_not_be_there";
|
let output = "tests/samples/output/should_not_be_there";
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use caesium;
|
|
||||||
use std::sync::Once;
|
use std::sync::Once;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue