-
Notifications
You must be signed in to change notification settings - Fork 145
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
High-level compression options API #503
Changes from 31 commits
6e258b5
b431bbf
72df368
54b89cf
c767438
e7dd3dc
8b08c9a
1e83f78
6b06728
b702a94
aed727a
dd547b0
17e7229
3194474
739a93a
cc8956a
104a048
c8b19c9
30192da
f07106b
085fba9
571ca49
eecf56c
f7adc08
2eaf588
d157df1
98f0c29
a96a3a2
111f7c2
7ba0fda
4c336eb
df73363
76b219a
a10a266
43489af
5af8a95
ca24d55
131d010
a5990f3
9a398c2
f9d27be
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
//! Common types shared between the encoder and decoder | ||
use crate::text_metadata::{EncodableTextChunk, ITXtChunk, TEXtChunk, ZTXtChunk}; | ||
#[allow(unused_imports)] // used by doc comments only | ||
use crate::Filter; | ||
use crate::{chunk, encoder}; | ||
use io::Write; | ||
use std::{borrow::Cow, convert::TryFrom, fmt, io}; | ||
|
@@ -303,33 +305,103 @@ impl AnimationControl { | |
} | ||
|
||
/// The type and strength of applied compression. | ||
/// | ||
/// This is a simple, high-level interface that will automatically choose | ||
/// the appropriate DEFLATE compression mode and PNG filter. | ||
/// | ||
/// If you need more control over the encoding paramters, | ||
/// you can set the [DeflateCompression] and [Filter] manually. | ||
#[derive(Debug, Clone, Copy)] | ||
#[non_exhaustive] | ||
pub enum Compression { | ||
/// Default level | ||
Default, | ||
/// Fast minimal compression | ||
Fast, | ||
/// Higher compression level | ||
/// No compression whatsoever. Fastest, but results in large files. | ||
NoCompression, | ||
/// Extremely fast but light compression. | ||
Fastest, | ||
/// Extremely fast compression with a decent compression ratio. | ||
/// | ||
/// 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, | ||
#[deprecated( | ||
since = "0.17.6", | ||
note = "use one of the other compression levels instead, such as 'fast'" | ||
)] | ||
Huffman, | ||
#[deprecated( | ||
since = "0.17.6", | ||
note = "use one of the other compression levels instead, such as 'fast'" | ||
)] | ||
Rle, | ||
/// Significantly outperforms libpng and other popular encoders | ||
/// by using a [specialized DEFLATE implementation tuned for PNG](https://crates.io/crates/fdeflate), | ||
/// while still providing better compression ratio than the fastest modes of other encoders. | ||
Fast, | ||
/// Balances encoding speed and compression ratio | ||
Balanced, | ||
kornelski marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/// Spend more time to produce a slightly smaller file than with `Default` | ||
High, | ||
} | ||
|
||
impl Default for Compression { | ||
fn default() -> Self { | ||
Self::Default | ||
Self::Balanced | ||
} | ||
} | ||
|
||
/// Advanced compression settings with more customization options than [Compression]. | ||
Shnatsel marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/// | ||
/// Note that this setting only affects DEFLATE compression. | ||
/// Another setting that influences the compression ratio and lets you choose | ||
/// between encoding speed and compression ratio is the [Filter]. | ||
/// | ||
/// ### Stability guarantees | ||
/// | ||
/// The implementation details of DEFLATE compression may evolve over time, | ||
/// even without a semver-breaking change to the version of `png` crate. | ||
/// | ||
/// If a certain compression setting is superseded by other options, | ||
/// it may be marked deprecated and remapped to a different option. | ||
/// You will see a deprecation notice when compiling code relying on such options. | ||
#[non_exhaustive] | ||
#[derive(Debug, Clone, Copy)] | ||
pub enum DeflateCompression { | ||
fintelia marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/// Do not compress the data at all. | ||
/// | ||
/// Useful for incompressible images, | ||
/// or when speed is paramount and you don't care about size at all. | ||
/// | ||
/// This mode also disables filters, forcing [Filter::NoFilter]. | ||
NoCompression, | ||
|
||
/// Excellent for creating lightly compressed PNG images very quickly. | ||
/// | ||
/// Uses the [fdeflate](https://crates.io/crates/fdeflate) crate under the hood | ||
/// to achieve speeds far exceeding what libpng is capable of | ||
/// while still providing a decent compression ratio. | ||
/// | ||
/// Images encoded in this mode can also be decoded by the `png` crate slightly faster than usual. | ||
/// Other decoders (e.g. libpng) do not get a decoding speed boost from this mode. | ||
FdeflateUltraFast, | ||
|
||
/// Uses [flate2](https://crates.io/crates/flate2) crate with the specified [compression level](flate2::Compression::new). | ||
/// | ||
/// Flate2 has several backends that make different trade-offs. | ||
/// See the flate2 documentation for the available backends for more information. | ||
Flate2(u32), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. After more experimentation with adding higher compression levels to One aspect is that the various different flate2 backends actually have a somewhat significant amount of variability about what each compression level means, so we wouldn't have to worry too much about exactly calibrating to match existing behavior. But additionally, these algorithms have like 5 to 10 different knobs to tune. So the challenge is really condensing them into a single number (which you want to do regardless, because users won't want to deal with setting all the parameters!) Long story short, I think we should drop the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TL;DR: since this is the advanced API, not the high-level one, I'd prefer to keep it I am going to calibrate Knowing that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On |
||
// TODO: Zopfli? | ||
Shnatsel marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
impl Default for DeflateCompression { | ||
fn default() -> Self { | ||
Self::from_simple(Compression::Balanced) | ||
} | ||
} | ||
|
||
impl DeflateCompression { | ||
pub(crate) fn from_simple(value: Compression) -> Self { | ||
match value { | ||
Compression::NoCompression => Self::NoCompression, | ||
Compression::Fastest => Self::FdeflateUltraFast, | ||
Compression::Fast => Self::FdeflateUltraFast, | ||
Compression::Balanced => Self::Flate2(flate2::Compression::default().level()), | ||
Compression::High => Self::Flate2(flate2::Compression::best().level()), | ||
} | ||
} | ||
|
||
pub(crate) fn closest_flate2_level(&self) -> flate2::Compression { | ||
match self { | ||
DeflateCompression::NoCompression => flate2::Compression::none(), | ||
DeflateCompression::FdeflateUltraFast => flate2::Compression::new(1), | ||
DeflateCompression::Flate2(level) => flate2::Compression::new(*level), | ||
} | ||
} | ||
} | ||
|
||
|
@@ -494,7 +566,8 @@ pub struct Info<'a> { | |
|
||
pub frame_control: Option<FrameControl>, | ||
pub animation_control: Option<AnimationControl>, | ||
pub compression: Compression, | ||
/// Controls the DEFLATE compression options. Influences the trade-off between compression speed and ratio, along with filters. | ||
pub compression_deflate: DeflateCompression, | ||
/// Gamma of the source system. | ||
/// Set by both `gAMA` as well as to a replacement by `sRGB` chunk. | ||
pub source_gamma: Option<ScaledFloat>, | ||
|
@@ -530,9 +603,7 @@ impl Default for Info<'_> { | |
pixel_dims: None, | ||
frame_control: None, | ||
animation_control: None, | ||
// Default to `deflate::Compression::Fast` and `filter::FilterType::Sub` | ||
// to maintain backward compatible output. | ||
compression: Compression::Fast, | ||
compression_deflate: DeflateCompression::default(), | ||
source_gamma: None, | ||
source_chromaticities: None, | ||
srgb: None, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A link backing up these claims would be nice here and in the new updated readme. It requires a bit of digging and research on the reader's part to confirm this.