blob: 6e823fa2cf3394a93be374487a43eea3ced7eba5 [file] [log] [blame]
//! This module contains the various options to tweak how compression is performed.
//!
//! Note that due to the nature of the `DEFLATE` format, lower compression levels
//! may for some data compress better than higher compression levels.
//!
//! For applications where a maximum level of compression (irrespective of compression
//! speed) is required, consider using the [`Zopfli`](https://crates.io/crates/zopfli)
//! compressor, which uses a specialised (but slow) algorithm to figure out the maximum
//! of compression for the provided data.
//!
use lz77::MatchingType;
use std::convert::From;
pub const HIGH_MAX_HASH_CHECKS: u16 = 1768;
pub const HIGH_LAZY_IF_LESS_THAN: u16 = 128;
/// The maximum number of hash checks that make sense as this is the length
/// of the hash chain.
pub const MAX_HASH_CHECKS: u16 = 32 * 1024;
pub const DEFAULT_MAX_HASH_CHECKS: u16 = 128;
pub const DEFAULT_LAZY_IF_LESS_THAN: u16 = 32;
/// An enum describing the level of compression to be used by the encoder
///
/// Higher compression ratios will take longer to encode.
///
/// This is a simplified interface to specify a compression level.
///
/// [See also `CompressionOptions`](./struct.CompressionOptions.html) which provides for
/// tweaking the settings more finely.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum Compression {
/// Fast minimal compression (`CompressionOptions::fast()`).
Fast,
/// Default level (`CompressionOptions::default()`).
Default,
/// Higher compression level (`CompressionOptions::high()`).
///
/// Best in this context isn't actually the highest possible level
/// the encoder can do, but is meant to emulate the `Best` setting in the `Flate2`
/// library.
Best,
}
impl Default for Compression {
fn default() -> Compression {
Compression::Default
}
}
/// Enum allowing some special options (not implemented yet)!
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum SpecialOptions {
/// Compress normally.
Normal,
/// Force fixed huffman tables. (Unimplemented!).
_ForceFixed,
/// Force stored (uncompressed) blocks only. (Unimplemented!).
_ForceStored,
}
impl Default for SpecialOptions {
fn default() -> SpecialOptions {
SpecialOptions::Normal
}
}
pub const DEFAULT_OPTIONS: CompressionOptions = CompressionOptions {
max_hash_checks: DEFAULT_MAX_HASH_CHECKS,
lazy_if_less_than: DEFAULT_LAZY_IF_LESS_THAN,
matching_type: MatchingType::Lazy,
special: SpecialOptions::Normal,
};
/// A struct describing the options for a compressor or compression function.
///
/// These values are not stable and still subject to change!
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct CompressionOptions {
/// The maximum number of checks to make in the hash table for matches.
///
/// Higher numbers mean slower, but better compression. Very high (say `>1024`) values
/// will impact compression speed a lot. The maximum match length is 2^15, so values higher than
/// this won't make any difference, and will be truncated to 2^15 by the compression
/// function/writer.
///
/// Default value: `128`
pub max_hash_checks: u16,
// pub _window_size: u16,
/// Only lazy match if we have a length less than this value.
///
/// Higher values degrade compression slightly, but improve compression speed.
///
/// * `0`: Never lazy match. (Same effect as setting MatchingType to greedy, but may be slower).
/// * `1...257`: Only check for a better match if the first match was shorter than this value.
/// * `258`: Always lazy match.
///
/// As the maximum length of a match is `258`, values higher than this will have
/// no further effect.
///
/// * Default value: `32`
pub lazy_if_less_than: u16,
// pub _decent_match: u16,
/// Whether to use lazy or greedy matching.
///
/// Lazy matching will provide better compression, at the expense of compression speed.
///
/// As a special case, if max_hash_checks is set to 0, and matching_type is set to lazy,
/// compression using only run-length encoding (i.e maximum match distance of 1) is performed.
/// (This may be changed in the future but is defined like this at the moment to avoid API
/// breakage.
///
/// [See `MatchingType`](./enum.MatchingType.html)
///
/// * Default value: `MatchingType::Lazy`
pub matching_type: MatchingType,
/// Force fixed/stored blocks (Not implemented yet).
/// * Default value: `SpecialOptions::Normal`
pub special: SpecialOptions,
}
// Some standard profiles for the compression options.
// Ord should be implemented at some point, but won't yet until the struct is stabilised.
impl CompressionOptions {
/// Returns compression settings rouhgly corresponding to the `HIGH(9)` setting in miniz.
pub fn high() -> CompressionOptions {
CompressionOptions {
max_hash_checks: HIGH_MAX_HASH_CHECKS,
lazy_if_less_than: HIGH_LAZY_IF_LESS_THAN,
matching_type: MatchingType::Lazy,
special: SpecialOptions::Normal,
}
}
/// Returns a fast set of compression settings
///
/// Ideally this should roughly correspond to the `FAST(1)` setting in miniz.
/// However, that setting makes miniz use a somewhat different algorhithm,
/// so currently hte fast level in this library is slower and better compressing
/// than the corresponding level in miniz.
pub fn fast() -> CompressionOptions {
CompressionOptions {
max_hash_checks: 1,
lazy_if_less_than: 0,
matching_type: MatchingType::Greedy,
special: SpecialOptions::Normal,
}
}
/// Returns a set of compression settings that makes the compressor only compress using
/// huffman coding. (Ignoring any length/distance matching)
///
/// This will normally have the worst compression ratio (besides only using uncompressed data),
/// but may be the fastest method in some cases.
pub fn huffman_only() -> CompressionOptions {
CompressionOptions {
max_hash_checks: 0,
lazy_if_less_than: 0,
matching_type: MatchingType::Greedy,
special: SpecialOptions::Normal,
}
}
/// Returns a set of compression settings that makes the compressor compress only using
/// run-length encoding (i.e only looking for matches one byte back).
///
/// This is very fast, but tends to compress worse than looking for more matches using hash
/// chains that the slower settings do.
/// Works best on data that has runs of equivialent bytes, like binary or simple images,
/// less good for text.
pub fn rle() -> CompressionOptions {
CompressionOptions {
max_hash_checks: 0,
lazy_if_less_than: 0,
matching_type: MatchingType::Lazy,
special: SpecialOptions::Normal,
}
}
}
impl Default for CompressionOptions {
/// Returns the options describing the default compression level.
fn default() -> CompressionOptions {
DEFAULT_OPTIONS
}
}
impl From<Compression> for CompressionOptions {
fn from(compression: Compression) -> CompressionOptions {
match compression {
Compression::Fast => CompressionOptions::fast(),
Compression::Default => CompressionOptions::default(),
Compression::Best => CompressionOptions::high(),
}
}
}