3 releases (breaking)
0.3.0 | Jan 21, 2020 |
---|---|
0.2.0 | Jan 10, 2019 |
0.1.0 | Nov 9, 2018 |
#274 in Compression
Used in wayk_core
205KB
5K
SLoC
gfwx-rs
Implementation of GFWX image compression algorithm developed by Graham Fyffe. Library uses rayon for parallelization as a default feature.
Getting Started
Prerequisites
To use the library you need to have Rust installed on your machine. The library works on stable Rust branch and doesn't require nightly.
Using
gfwx-rs is available on crates.io. The recommended way to use it is to add a line into your Cargo.toml such as:
[dependencies]
gfwx = "0.2"
or, if you don't want to use rayon:
[dependencies]
gfwx = { version = "0.2", default-features = false }
Basic usage for compression:
extern crate gfwx;
fn main() {
let image = ...;
let builder = gfwx::HeaderBuilder {
width: image.width(),
height: image.height(),
layers: 1,
channels: image.channels(),
quality: gfwx::QUALITY_MAX,
chroma_scale: 8,
block_size: gfwx::BLOCK_DEFAULT,
filter: gfwx::Filter::Linear,
encoder: gfwx::Encoder::Turbo,
intent: gfwx::Intent::RGBA,
metadata_size: 0,
};
let header = builder.build().unwrap();
let buffer = vec![0; 2 * image.len()]; // 2 times original size should always be enough
header.encode(&mut buffer)?;
let gfwx_size = gfwx::compress_simple(
image.as_slice(),
&header,
&gfwx::ColorTransformProgram::new(), // no color transform
&mut buffer,
).unwrap();
buffer.truncate(gfwx_size);
}
Basic usage for decompression:
extern crate gfwx;
fn main() {
let mut compressed = ...;
let header = gfwx::Header::decode(&mut compressed).unwrap();
let mut decompressed = vec![0; header.get_estimated_decompress_buffer_size()];
let next_point_of_interest = gfwx::decompress_simple(
&mut compressed,
&header,
0, // no downsamping
false, // do not test, full decompress
&mut decompressed,
).unwrap();
...
}
Running the tests
Unit tests
To run unit tests:
cargo test
There are also tests for the case when build should fail. You can run them with
cargo test --features test_build_fails
Functional tests
To run functional tests, that use actual images, you can use ci/func_tests.sh
:
ci/func_tests.sh ci/test_images/
This command will build reference application, build examples and run functional tests
using prepared images in ci/test_images/
folder in the /tmp/gfwx
directory
(so working directory stays clean).
Benchmarks
There are also criterion benchmarks which you can run with
cargo bench
Examples
Examples folder contains 3 applications:
compress
- compresses an input image to gfwxdecompress
- decompresses a gfwx filecompare
- compares two images excluding metadata. Useful for comparing the input image and the decompressed one, because they may have the same "pixels" but different metadata, which means these files will have different checksum
Features
Library supports all features of original implementation except:
- It only supports u8 data, when original implementation supports 8-bit and 16-bit data both signed and unsigned
- Bayer mode is not supported
However, original implementation supports only channels in interleaved format (for example, [R1, G1, B1, R2, B2, G2, ...]) and always transform channels to planar format. This is not suitable for color spaces which already use planar channel format (for example, YUV420).
For this type of data, our library provides low-level compress_aux_data
and decompress_aux_data
functions.
This functions do not encode header, execute and encode ColorTransformProgram and accept 16-bit image data in planar channels format with boost already applied.
These functions are a little bit more complex to use, but provide more flexibility in case you need only image data compression and decompression.
You can manually encode the header with Header::encode()
, encode ColorTransformProgram
with ColorTransformProgram::encode()
and execute it and apply boost with ColorTransformProgram::transform()
(for planar channels) and ColorTransformProgram::transform_and_to_planar()
(for interleaved channels).
Also, instead of using ColorTransformProgram
you can use interleaved_to_planar()
and planar_to_interleaved()
that also can skip some channels during transformation (for example, skip Alpha channel in RGBA).
You can find a complete example on how to use these functions in examples/test_app.rs
or by looking into compress_simple
and decompress_simple
implementation in src/lib.rs
.
Dependencies
~3.5MB
~77K SLoC