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. Library works on stable Rust branch and doesn't require nightly.
Using
Add this to your Cargo.toml:
[dependencies]
gfwx = { path = "path/to/gfwx-rs" }
If you don't want to use rayon:
[dependencies]
gfwx = { path = "path/to/gfwx-rs", default-features = false }
Basic usage for compression:
extern crate gfwx;
Basic usage for decompression:
extern crate gfwx;
You can find a complete example in examples/test_app.rs
.
Running the tests
Unit tests
To run unit tests:
cargo test
There are also a test for the case when build should fail. You can run it with
cargo test --features test_build_fails
Benchmarks
There are also criterion benchmarks which you can run with
cargo bench
Examples
Examples folder contains 4 components:
test_app
- compresses an input image to gfwx, writes it to the file, and decompresses it back to the input format with given optionscompare
- 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 checksumreference_app
- folder with source code of test app created with original GFWX implementation. Usefull for comparing GFWX produced by library and the reference implementation.test_helper.py
- automatically checks compression and decompression for all the .png images in the specified folder. This script uses other binaries that must be located in the same folder.
To build reference application, you need CMake and OpenCV to be installed on your system. Then:
Features
Library support all features of original implementation except:
- It only support u8 data, when original implementation support 8-bit and 16-bit data both signed and unsigned
- Bayer mode is not supported
However, original implementation supports only channels in parallel order (for example, [R1, G1, B1, R2, B2, G2, ...]) and always transform channels to sequential order.
This is not suitable for colot spaces which already use sequential channel order (for example, YUV420). For this data out library provides compress_sequential_channels
and decompress_sequential_channels
functions which doesn't change order of the channels.
YUV420 support
This library also provides functions to convert from RGBA32 to YUV420 and back. But unfortunately, GFWX doesn't support channels of different size, which is the case of YUV420.
As a workaround, library provides yuv420_to_sequential_yuv444
and sequential_yuv444_to_yuv420
functions, that transform YUV420 to YUV444 but with sequantial channels order.
We found out that usage of YUV444 as an internal format (instead of RGB, for example) increases compression ratio and speed, even considering time required for transformation.
test_app
performs transformation from image intent to YUV444 (through YUV420 for demo purposes) if '--intent yuv420' option was passed:
let yuv420 = rgba32_to_yuv420;
let yuv444 = yuv420_to_sequential_yuv444;
compress_sequential_channels?;
...
decompress_sequential_channels?
let yuv420 = sequential_yuv444_to_yuv420;
let rgba32 = yuv420_to_rgba32;