diff --git a/.idea/markdown.xml b/.idea/markdown.xml
new file mode 100644
index 0000000..e6da414
--- /dev/null
+++ b/.idea/markdown.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
index 0c7fded..0c99857 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,8 +1,8 @@
[package]
name = "libcaesium"
-version = "0.7.0"
+version = "0.8.0"
authors = ["Matteo Paonessa "]
-edition = "2018"
+edition = "2021"
categories = ["multimedia::images"]
keywords = [
"compression",
@@ -24,17 +24,17 @@ license = "Apache-2.0"
[dependencies]
mozjpeg-sys = "1.0.1"
oxipng = "5.0.1"
-libc = "0.2.76"
+libc = "0.2.119"
gifsicle = "1.92.5"
webp = "0.2.1"
-infer = "0.6.0"
+infer = "0.7.0"
image = { version = "0.24", default-features = false, features = ["jpeg", "png", "webp", "gif"] }
img-parts = "0.2.3"
bytes = "1.1.0"
[dev-dependencies]
dssim = "3.2.0"
-kamadak-exif = "0.5.0"
+kamadak-exif = "0.5.4"
[lib]
name = "caesium"
diff --git a/README.md b/README.md
index e948115..412b91f 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@ pub fn compress(
- `output_path` - output file path (full filename)
- `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
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:
@@ -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.
- `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 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`.
#### 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
pub struct Parameters {
pub quality: u32,
@@ -84,14 +84,23 @@ pub extern fn c_compress(
input_path: *const c_char,
output_path: *const c_char,
params: CCSParameters
-) -> bool
+) -> CCSResult
```
#### Parameters
- `input_path` - input file path (full filename)
- `output_path` - output file path (full filename)
- `parameters` - options struct, containing compression parameters (see below)
#### 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
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).
PNG is lossless, so libcaesium will always perform optimization rather than compression.
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
diff --git a/src/jpeg.rs b/src/jpeg.rs
index a26e73a..8e0c552 100644
--- a/src/jpeg.rs
+++ b/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)?;
+
if parameters.width > 0 || parameters.height > 0 {
if parameters.keep_metadata {
let metadata = extract_metadata(in_file.clone());
@@ -27,12 +28,11 @@ pub fn compress(input_path: String, output_path: String, parameters: CSParameter
}
unsafe {
- let compression_buffer: (*mut u8, u64);
- if parameters.optimize {
- compression_buffer = lossless(in_file, parameters)?;
+ let compression_buffer: (*mut u8, u64) = if parameters.optimize {
+ lossless(in_file, parameters)?
} else {
- compression_buffer = lossy(in_file, parameters)?;
- }
+ lossy(in_file, parameters)?
+ };
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))?;
}
diff --git a/src/lib.rs b/src/lib.rs
index b36b1b1..41a8352 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -7,7 +7,7 @@ mod resize;
use std::error::Error;
use crate::utils::get_filetype;
-use std::ffi::CStr;
+use std::ffi::{CStr, CString};
use std::os::raw::c_char;
#[repr(C)]
@@ -23,6 +23,12 @@ pub struct CCSParameters {
pub height: u32,
}
+#[repr(C)]
+pub struct CCSResult {
+ pub success: bool,
+ pub error_message: *const c_char,
+}
+
pub struct CSParameters {
pub jpeg: jpeg::Parameters,
pub png: png::Parameters,
@@ -68,8 +74,9 @@ pub fn initialize_parameters() -> CSParameters
#[no_mangle]
#[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();
+
parameters.jpeg.quality = params.jpeg_quality;
parameters.png.level = params.png_level;
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.height = params.height;
- let x = compress(CStr::from_ptr(input_path).to_str().unwrap().to_string(),
- CStr::from_ptr(output_path).to_str().unwrap().to_string(),
- parameters).is_ok();
- x
+ let mut error_message = CString::new("").unwrap();
+
+ match compress(CStr::from_ptr(input_path).to_str().unwrap().to_string(),
+ 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> {
@@ -92,43 +118,21 @@ pub fn compress(input_path: String, output_path: String, parameters: CSParameter
match file_type {
utils::SupportedFileTypes::Jpeg => {
- return match jpeg::compress(input_path, output_path, parameters) {
- Ok(_) => Ok(()),
- Err(e) => {
- eprintln!("JPEG compression error: {}", e.to_string());
- Err(e.into())
- }
- };
+ jpeg::compress(input_path, output_path, parameters)?;
}
utils::SupportedFileTypes::Png => {
- return match png::compress(input_path, output_path, parameters) {
- Ok(_) => Ok(()),
- Err(e) => {
- eprintln!("PNG compression error: {}", e.to_string());
- Err(e.into())
- }
- };
+ png::compress(input_path, output_path, parameters)?;
}
utils::SupportedFileTypes::Gif => {
- return match gif::compress(input_path, output_path, parameters) {
- Ok(_) => Ok(()),
- Err(e) => {
- eprintln!("GIF compression error: {}", e.to_string());
- Err(e.into())
- }
- };
+ gif::compress(input_path, output_path, parameters)?;
}
utils::SupportedFileTypes::WebP => {
- return match webp::compress(input_path, output_path, parameters) {
- Ok(_) => Ok(()),
- Err(e) => {
- eprintln!("WebP compression error: {}", e.to_string());
- Err(e.into())
- }
- };
+ webp::compress(input_path, output_path, parameters)?;
}
_ => return Err("Unknown file type".into())
}
+
+ Ok(())
}
fn validate_parameters(parameters: &CSParameters) -> Result<(), Box> {
diff --git a/tests/integration.rs b/tests/integration.rs
index 5b2cd7c..b70d469 100644
--- a/tests/integration.rs
+++ b/tests/integration.rs
@@ -1,5 +1,3 @@
-use caesium;
-
#[test]
fn unknown_file_type() {
let output = "tests/samples/output/should_not_be_there";
diff --git a/tests/webp.rs b/tests/webp.rs
index d8ab630..b446287 100644
--- a/tests/webp.rs
+++ b/tests/webp.rs
@@ -1,4 +1,3 @@
-use caesium;
use std::sync::Once;
use std::fs;