Skip to content

Commit 83e6d64

Browse files
authored
Create feature flags for more compression algorithms (#270)
1 parent dc2c674 commit 83e6d64

File tree

8 files changed

+64
-15
lines changed

8 files changed

+64
-15
lines changed

.github/workflows/rust.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,19 @@ jobs:
3232
if: ${{ matrix.rust != '1.74.0' }}
3333
run: cargo test -v && cargo doc -v
3434

35+
features:
36+
runs-on: ubuntu-latest
37+
strategy:
38+
matrix:
39+
feature: ["", deflate, jpeg, lzw, zstd, default, "default,zstd"]
40+
steps:
41+
- uses: actions/checkout@v2
42+
- uses: dtolnay/rust-toolchain@stable
43+
with:
44+
components: clippy
45+
- name: Cargo check
46+
run: cargo check --features "${{ matrix.feature }}" --no-default-features
47+
3548
rustfmt:
3649
runs-on: ubuntu-latest
3750
steps:

Cargo.toml

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,23 @@ exclude = ["tests/images/*", "tests/fuzz_images/*"]
1818

1919
[dependencies]
2020
half = { version = "2.4.1" }
21-
weezl = "0.1.0"
22-
zune-jpeg = "0.4.17"
23-
flate2 = "1.0.20"
24-
zstd = { version = "0.13", optional = true }
2521
quick-error = "2.0.1"
2622

23+
flate2 = { version = "1.0.20", optional = true }
24+
weezl = { version = "0.1.0", optional = true }
25+
zstd = { version = "0.13", optional = true }
26+
zune-jpeg = { version = "0.4.17", optional = true }
27+
2728
[dev-dependencies]
2829
criterion = "0.3.1"
2930

3031
[features]
32+
default = ["deflate", "jpeg", "lzw"]
33+
34+
# Compression algorithms
35+
deflate = ["dep:flate2"]
36+
jpeg = ["dep:zune-jpeg"]
37+
lzw = ["dep:weezl"]
3138
zstd = ["dep:zstd"]
3239

3340
[[bench]]

src/decoder/image.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::ifd::{Directory, Value};
2-
use super::stream::{ByteOrder, DeflateReader, LZWReader, PackBitsReader};
2+
use super::stream::{ByteOrder, PackBitsReader};
33
use super::tag_reader::TagReader;
44
use super::{predict_f16, predict_f32, predict_f64, Limits};
55
use super::{stream::EndianReader, ChunkType};
@@ -9,7 +9,6 @@ use crate::tags::{
99
use crate::{ColorType, TiffError, TiffFormatError, TiffResult, TiffUnsupportedError, UsageError};
1010
use std::io::{self, Cursor, Read, Seek};
1111
use std::sync::Arc;
12-
use zune_jpeg::zune_core;
1312

1413
#[derive(Debug)]
1514
pub(crate) struct StripDecodeState {
@@ -370,23 +369,29 @@ impl Image {
370369

371370
fn create_reader<'r, R: 'r + Read>(
372371
reader: R,
373-
photometric_interpretation: PhotometricInterpretation,
372+
#[allow(unused_variables)] photometric_interpretation: PhotometricInterpretation,
374373
compression_method: CompressionMethod,
375374
compressed_length: u64,
376-
jpeg_tables: Option<&[u8]>,
375+
#[allow(unused_variables)] jpeg_tables: Option<&[u8]>,
377376
) -> TiffResult<Box<dyn Read + 'r>> {
378377
Ok(match compression_method {
379378
CompressionMethod::None => Box::new(reader),
380-
CompressionMethod::LZW => {
381-
Box::new(LZWReader::new(reader, usize::try_from(compressed_length)?))
382-
}
379+
#[cfg(feature = "lzw")]
380+
CompressionMethod::LZW => Box::new(super::stream::LZWReader::new(
381+
reader,
382+
usize::try_from(compressed_length)?,
383+
)),
383384
#[cfg(feature = "zstd")]
384385
CompressionMethod::ZSTD => Box::new(zstd::Decoder::new(reader)?),
385386
CompressionMethod::PackBits => Box::new(PackBitsReader::new(reader, compressed_length)),
387+
#[cfg(feature = "deflate")]
386388
CompressionMethod::Deflate | CompressionMethod::OldDeflate => {
387-
Box::new(DeflateReader::new(reader))
389+
Box::new(super::stream::DeflateReader::new(reader))
388390
}
391+
#[cfg(feature = "jpeg")]
389392
CompressionMethod::ModernJPEG => {
393+
use zune_jpeg::zune_core;
394+
390395
if jpeg_tables.is_some() && compressed_length < 2 {
391396
return Err(TiffError::FormatError(
392397
TiffFormatError::InvalidTagValueType(Tag::JPEGTables),

src/decoder/stream.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,18 +140,21 @@ impl<R: Read + Seek> EndianReader<R> {
140140
/// ## Deflate Reader
141141
///
142142
143+
#[cfg(feature = "deflate")]
143144
pub type DeflateReader<R> = flate2::read::ZlibDecoder<R>;
144145

145146
///
146147
/// ## LZW Reader
147148
///
148149
149150
/// Reader that decompresses LZW streams
151+
#[cfg(feature = "lzw")]
150152
pub struct LZWReader<R: Read> {
151153
reader: BufReader<Take<R>>,
152154
decoder: weezl::decode::Decoder,
153155
}
154156

157+
#[cfg(feature = "lzw")]
155158
impl<R: Read> LZWReader<R> {
156159
/// Wraps a reader
157160
pub fn new(reader: R, compressed_length: usize) -> LZWReader<R> {
@@ -165,6 +168,7 @@ impl<R: Read> LZWReader<R> {
165168
}
166169
}
167170

171+
#[cfg(feature = "lzw")]
168172
impl<R: Read> Read for LZWReader<R> {
169173
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
170174
loop {

src/encoder/compression/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
use crate::tags::CompressionMethod;
22
use std::io::{self, Write};
33

4+
#[cfg(feature = "deflate")]
45
mod deflate;
6+
#[cfg(feature = "lzw")]
57
mod lzw;
68
mod packbits;
79
mod uncompressed;
810

11+
#[cfg(feature = "deflate")]
912
pub use self::deflate::{Deflate, DeflateLevel};
13+
14+
#[cfg(feature = "lzw")]
1015
pub use self::lzw::Lzw;
16+
1117
pub use self::packbits::Packbits;
1218
pub use self::uncompressed::Uncompressed;
1319

@@ -30,7 +36,9 @@ pub trait Compression: CompressionAlgorithm {
3036
/// An enum to store each compression algorithm.
3137
pub enum Compressor {
3238
Uncompressed(Uncompressed),
39+
#[cfg(feature = "lzw")]
3340
Lzw(Lzw),
41+
#[cfg(feature = "deflate")]
3442
Deflate(Deflate),
3543
Packbits(Packbits),
3644
}
@@ -46,7 +54,9 @@ impl CompressionAlgorithm for Compressor {
4654
fn write_to<W: Write>(&mut self, writer: &mut W, bytes: &[u8]) -> Result<u64, io::Error> {
4755
match self {
4856
Compressor::Uncompressed(algorithm) => algorithm.write_to(writer, bytes),
57+
#[cfg(feature = "lzw")]
4958
Compressor::Lzw(algorithm) => algorithm.write_to(writer, bytes),
59+
#[cfg(feature = "deflate")]
5060
Compressor::Deflate(algorithm) => algorithm.write_to(writer, bytes),
5161
Compressor::Packbits(algorithm) => algorithm.write_to(writer, bytes),
5262
}

src/encoder/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,15 @@ use self::writer::*;
3434
///
3535
/// [Predictor::FloatingPoint] is currently not supported.
3636
pub type Predictor = crate::tags::Predictor;
37+
#[cfg(feature = "deflate")]
3738
pub type DeflateLevel = compression::DeflateLevel;
3839

3940
#[derive(Clone, Copy, PartialEq)]
4041
pub enum Compression {
4142
Uncompressed,
43+
#[cfg(feature = "lzw")]
4244
Lzw,
45+
#[cfg(feature = "deflate")]
4346
Deflate(DeflateLevel),
4447
Packbits,
4548
}
@@ -54,7 +57,9 @@ impl Compression {
5457
fn tag(&self) -> CompressionMethod {
5558
match self {
5659
Compression::Uncompressed => CompressionMethod::None,
60+
#[cfg(feature = "lzw")]
5761
Compression::Lzw => CompressionMethod::LZW,
62+
#[cfg(feature = "deflate")]
5863
Compression::Deflate(_) => CompressionMethod::Deflate,
5964
Compression::Packbits => CompressionMethod::PackBits,
6065
}
@@ -63,7 +68,9 @@ impl Compression {
6368
fn get_algorithm(&self) -> Compressor {
6469
match self {
6570
Compression::Uncompressed => compression::Uncompressed {}.get_algorithm(),
71+
#[cfg(feature = "lzw")]
6672
Compression::Lzw => compression::Lzw {}.get_algorithm(),
73+
#[cfg(feature = "deflate")]
6774
Compression::Deflate(level) => compression::Deflate::with_level(*level).get_algorithm(),
6875
Compression::Packbits => compression::Packbits {}.get_algorithm(),
6976
}

src/error.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use std::str;
33
use std::string;
44

55
use quick_error::quick_error;
6-
use weezl::LzwError;
76

87
use crate::decoder::ChunkType;
98
use crate::tags::{
@@ -206,12 +205,14 @@ impl From<std::num::TryFromIntError> for TiffError {
206205
}
207206
}
208207

209-
impl From<LzwError> for TiffError {
210-
fn from(err: LzwError) -> TiffError {
208+
#[cfg(feature = "lzw")]
209+
impl From<weezl::LzwError> for TiffError {
210+
fn from(err: weezl::LzwError) -> TiffError {
211211
TiffError::FormatError(TiffFormatError::CompressedDataCorrupt(err.to_string()))
212212
}
213213
}
214214

215+
#[cfg(feature = "jpeg")]
215216
impl From<zune_jpeg::errors::DecodeErrors> for TiffError {
216217
fn from(err: zune_jpeg::errors::DecodeErrors) -> Self {
217218
TiffError::FormatError(TiffFormatError::CompressedDataCorrupt(err.to_string()))

tests/encode_images_with_compression.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,13 @@ fn encode_decode_without_compression() {
139139
}
140140

141141
#[test]
142+
#[cfg(feature = "lzw")]
142143
fn encode_decode_with_lzw() {
143144
encode_decode_with_compression(Compression::Lzw);
144145
}
145146

146147
#[test]
148+
#[cfg(feature = "deflate")]
147149
fn encode_decode_with_deflate() {
148150
encode_decode_with_compression(Compression::Deflate(DeflateLevel::Fast));
149151
encode_decode_with_compression(Compression::Deflate(DeflateLevel::Balanced));

0 commit comments

Comments
 (0)