|
1 | 1 | //! Common types shared between the encoder and decoder
|
2 | 2 | use crate::text_metadata::{ITXtChunk, TEXtChunk, ZTXtChunk};
|
| 3 | +#[allow(unused_imports)] // used by doc comments only |
| 4 | +use crate::Filter; |
3 | 5 | use crate::{chunk, encoder};
|
4 | 6 | use io::Write;
|
5 | 7 | use std::{borrow::Cow, convert::TryFrom, fmt, io};
|
@@ -313,33 +315,103 @@ impl AnimationControl {
|
313 | 315 | }
|
314 | 316 |
|
315 | 317 | /// The type and strength of applied compression.
|
| 318 | +/// |
| 319 | +/// This is a simple, high-level interface that will automatically choose |
| 320 | +/// the appropriate DEFLATE compression mode and PNG filter. |
| 321 | +/// |
| 322 | +/// If you need more control over the encoding paramters, |
| 323 | +/// you can set the [DeflateCompression] and [Filter] manually. |
316 | 324 | #[derive(Debug, Clone, Copy)]
|
| 325 | +#[non_exhaustive] |
317 | 326 | pub enum Compression {
|
318 |
| - /// Default level |
319 |
| - Default, |
320 |
| - /// Fast minimal compression |
321 |
| - Fast, |
322 |
| - /// Higher compression level |
| 327 | + /// No compression whatsoever. Fastest, but results in large files. |
| 328 | + NoCompression, |
| 329 | + /// Extremely fast but light compression. |
| 330 | + Fastest, |
| 331 | + /// Extremely fast compression with a decent compression ratio. |
323 | 332 | ///
|
324 |
| - /// Best in this context isn't actually the highest possible level |
325 |
| - /// the encoder can do, but is meant to emulate the `Best` setting in the `Flate2` |
326 |
| - /// library. |
327 |
| - Best, |
328 |
| - #[deprecated( |
329 |
| - since = "0.17.6", |
330 |
| - note = "use one of the other compression levels instead, such as 'fast'" |
331 |
| - )] |
332 |
| - Huffman, |
333 |
| - #[deprecated( |
334 |
| - since = "0.17.6", |
335 |
| - note = "use one of the other compression levels instead, such as 'fast'" |
336 |
| - )] |
337 |
| - Rle, |
| 333 | + /// Significantly outperforms libpng and other popular encoders |
| 334 | + /// by using a [specialized DEFLATE implementation tuned for PNG](https://crates.io/crates/fdeflate), |
| 335 | + /// while still providing better compression ratio than the fastest modes of other encoders. |
| 336 | + Fast, |
| 337 | + /// Balances encoding speed and compression ratio |
| 338 | + Balanced, |
| 339 | + /// Spend more time to produce a slightly smaller file than with `Default` |
| 340 | + High, |
338 | 341 | }
|
339 | 342 |
|
340 | 343 | impl Default for Compression {
|
341 | 344 | fn default() -> Self {
|
342 |
| - Self::Default |
| 345 | + Self::Balanced |
| 346 | + } |
| 347 | +} |
| 348 | + |
| 349 | +/// Advanced compression settings with more customization options than [Compression]. |
| 350 | +/// |
| 351 | +/// Note that this setting only affects DEFLATE compression. |
| 352 | +/// Another setting that influences the compression ratio and lets you choose |
| 353 | +/// between encoding speed and compression ratio is the [Filter]. |
| 354 | +/// |
| 355 | +/// ### Stability guarantees |
| 356 | +/// |
| 357 | +/// The implementation details of DEFLATE compression may evolve over time, |
| 358 | +/// even without a semver-breaking change to the version of `png` crate. |
| 359 | +/// |
| 360 | +/// If a certain compression setting is superseded by other options, |
| 361 | +/// it may be marked deprecated and remapped to a different option. |
| 362 | +/// You will see a deprecation notice when compiling code relying on such options. |
| 363 | +#[non_exhaustive] |
| 364 | +#[derive(Debug, Clone, Copy)] |
| 365 | +pub enum DeflateCompression { |
| 366 | + /// Do not compress the data at all. |
| 367 | + /// |
| 368 | + /// Useful for incompressible images, |
| 369 | + /// or when speed is paramount and you don't care about size at all. |
| 370 | + /// |
| 371 | + /// This mode also disables filters, forcing [Filter::NoFilter]. |
| 372 | + NoCompression, |
| 373 | + |
| 374 | + /// Excellent for creating lightly compressed PNG images very quickly. |
| 375 | + /// |
| 376 | + /// Uses the [fdeflate](https://crates.io/crates/fdeflate) crate under the hood |
| 377 | + /// to achieve speeds far exceeding what libpng is capable of |
| 378 | + /// while still providing a decent compression ratio. |
| 379 | + /// |
| 380 | + /// Images encoded in this mode can also be decoded by the `png` crate slightly faster than usual. |
| 381 | + /// Other decoders (e.g. libpng) do not get a decoding speed boost from this mode. |
| 382 | + FdeflateUltraFast, |
| 383 | + |
| 384 | + /// Uses [flate2](https://crates.io/crates/flate2) crate with the specified [compression level](flate2::Compression::new). |
| 385 | + /// |
| 386 | + /// Flate2 has several backends that make different trade-offs. |
| 387 | + /// See the flate2 documentation for the available backends for more information. |
| 388 | + Flate2(u8), |
| 389 | + // Other variants can be added in the future |
| 390 | +} |
| 391 | + |
| 392 | +impl Default for DeflateCompression { |
| 393 | + fn default() -> Self { |
| 394 | + Self::from_simple(Compression::Balanced) |
| 395 | + } |
| 396 | +} |
| 397 | + |
| 398 | +impl DeflateCompression { |
| 399 | + pub(crate) fn from_simple(value: Compression) -> Self { |
| 400 | + match value { |
| 401 | + Compression::NoCompression => Self::NoCompression, |
| 402 | + Compression::Fastest => Self::FdeflateUltraFast, |
| 403 | + Compression::Fast => Self::FdeflateUltraFast, |
| 404 | + Compression::Balanced => Self::Flate2(flate2::Compression::default().level() as u8), |
| 405 | + Compression::High => Self::Flate2(flate2::Compression::best().level() as u8), |
| 406 | + } |
| 407 | + } |
| 408 | + |
| 409 | + pub(crate) fn closest_flate2_level(&self) -> flate2::Compression { |
| 410 | + match self { |
| 411 | + DeflateCompression::NoCompression => flate2::Compression::none(), |
| 412 | + DeflateCompression::FdeflateUltraFast => flate2::Compression::new(1), |
| 413 | + DeflateCompression::Flate2(level) => flate2::Compression::new(u32::from(*level)), |
| 414 | + } |
343 | 415 | }
|
344 | 416 | }
|
345 | 417 |
|
|
0 commit comments