1use std::collections::HashMap;
4use std::fmt::Debug;
5use std::io::{Cursor, Read};
6
7use bytes::Bytes;
8use flate2::bufread::ZlibDecoder;
9
10use crate::error::{AsyncTiffResult, TiffError, TiffUnsupportedError};
11use crate::tags::{CompressionMethod, PhotometricInterpretation};
12
13#[derive(Debug)]
28pub struct DecoderRegistry(HashMap<CompressionMethod, Box<dyn Decoder>>);
29
30impl DecoderRegistry {
31 pub fn empty() -> Self {
33 Self(HashMap::new())
34 }
35}
36
37impl AsRef<HashMap<CompressionMethod, Box<dyn Decoder>>> for DecoderRegistry {
38 fn as_ref(&self) -> &HashMap<CompressionMethod, Box<dyn Decoder>> {
39 &self.0
40 }
41}
42
43impl AsMut<HashMap<CompressionMethod, Box<dyn Decoder>>> for DecoderRegistry {
44 fn as_mut(&mut self) -> &mut HashMap<CompressionMethod, Box<dyn Decoder>> {
45 &mut self.0
46 }
47}
48
49impl Default for DecoderRegistry {
50 fn default() -> Self {
51 let mut registry = HashMap::with_capacity(6);
52 registry.insert(CompressionMethod::None, Box::new(UncompressedDecoder) as _);
53 registry.insert(CompressionMethod::Deflate, Box::new(DeflateDecoder) as _);
54 registry.insert(CompressionMethod::OldDeflate, Box::new(DeflateDecoder) as _);
55 registry.insert(CompressionMethod::LZW, Box::new(LZWDecoder) as _);
56 registry.insert(CompressionMethod::ModernJPEG, Box::new(JPEGDecoder) as _);
57 registry.insert(CompressionMethod::ZSTD, Box::new(ZstdDecoder) as _);
58 #[cfg(feature = "jpeg2k")]
59 registry.insert(CompressionMethod::JPEG2k, Box::new(JPEG2kDecoder) as _);
60 Self(registry)
61 }
62}
63
64pub trait Decoder: Debug + Send + Sync {
66 fn decode_tile(
68 &self,
69 buffer: Bytes,
70 photometric_interpretation: PhotometricInterpretation,
71 jpeg_tables: Option<&[u8]>,
72 ) -> AsyncTiffResult<Vec<u8>>;
73}
74
75#[derive(Debug, Clone)]
77pub struct DeflateDecoder;
78
79impl Decoder for DeflateDecoder {
80 fn decode_tile(
81 &self,
82 buffer: Bytes,
83 _photometric_interpretation: PhotometricInterpretation,
84 _jpeg_tables: Option<&[u8]>,
85 ) -> AsyncTiffResult<Vec<u8>> {
86 let mut decoder = ZlibDecoder::new(Cursor::new(buffer));
87 let mut buf = Vec::new();
88 decoder.read_to_end(&mut buf)?;
89 Ok(buf)
90 }
91}
92
93#[derive(Debug, Clone)]
95pub struct JPEGDecoder;
96
97impl Decoder for JPEGDecoder {
98 fn decode_tile(
99 &self,
100 buffer: Bytes,
101 photometric_interpretation: PhotometricInterpretation,
102 jpeg_tables: Option<&[u8]>,
103 ) -> AsyncTiffResult<Vec<u8>> {
104 decode_modern_jpeg(buffer, photometric_interpretation, jpeg_tables)
105 }
106}
107
108#[derive(Debug, Clone)]
110pub struct LZWDecoder;
111
112impl Decoder for LZWDecoder {
113 fn decode_tile(
114 &self,
115 buffer: Bytes,
116 _photometric_interpretation: PhotometricInterpretation,
117 _jpeg_tables: Option<&[u8]>,
118 ) -> AsyncTiffResult<Vec<u8>> {
119 let mut decoder = weezl::decode::Decoder::with_tiff_size_switch(weezl::BitOrder::Msb, 8);
121 let decoded = decoder.decode(&buffer).expect("failed to decode LZW data");
122 Ok(decoded)
123 }
124}
125
126#[cfg(feature = "jpeg2k")]
128#[derive(Debug, Clone)]
129pub struct JPEG2kDecoder;
130
131#[cfg(feature = "jpeg2k")]
132impl Decoder for JPEG2kDecoder {
133 fn decode_tile(
134 &self,
135 buffer: Bytes,
136 _photometric_interpretation: PhotometricInterpretation,
137 _jpeg_tables: Option<&[u8]>,
138 ) -> AsyncTiffResult<Vec<u8>> {
139 let decoder = jpeg2k::DecodeParameters::new();
140
141 let image = jpeg2k::Image::from_bytes_with(&buffer, decoder)?;
142
143 let id = image.get_pixels(None)?;
144 match id.data {
145 jpeg2k::ImagePixelData::L8(items)
146 | jpeg2k::ImagePixelData::La8(items)
147 | jpeg2k::ImagePixelData::Rgb8(items)
148 | jpeg2k::ImagePixelData::Rgba8(items) => Ok(items),
149 jpeg2k::ImagePixelData::L16(items)
150 | jpeg2k::ImagePixelData::La16(items)
151 | jpeg2k::ImagePixelData::Rgb16(items)
152 | jpeg2k::ImagePixelData::Rgba16(items) => Ok(bytemuck::cast_vec(items)),
153 }
154 }
155}
156
157#[derive(Debug, Clone)]
159pub struct UncompressedDecoder;
160
161impl Decoder for UncompressedDecoder {
162 fn decode_tile(
163 &self,
164 buffer: Bytes,
165 _photometric_interpretation: PhotometricInterpretation,
166 _jpeg_tables: Option<&[u8]>,
167 ) -> AsyncTiffResult<Vec<u8>> {
168 Ok(buffer.to_vec())
169 }
170}
171
172#[derive(Debug, Clone)]
174pub struct ZstdDecoder;
175
176impl Decoder for ZstdDecoder {
177 fn decode_tile(
178 &self,
179 buffer: Bytes,
180 _photometric_interpretation: PhotometricInterpretation,
181 _jpeg_tables: Option<&[u8]>,
182 ) -> AsyncTiffResult<Vec<u8>> {
183 let mut decoder = zstd::Decoder::new(Cursor::new(buffer))?;
184 let mut buf = Vec::new();
185 decoder.read_to_end(&mut buf)?;
186 Ok(buf)
187 }
188}
189
190fn decode_modern_jpeg(
192 buf: Bytes,
193 photometric_interpretation: PhotometricInterpretation,
194 jpeg_tables: Option<&[u8]>,
195) -> AsyncTiffResult<Vec<u8>> {
196 let reader = Cursor::new(buf);
207
208 let jpeg_reader = match jpeg_tables {
209 Some(jpeg_tables) => {
210 let mut reader = reader;
211 reader.read_exact(&mut [0; 2])?;
212
213 Box::new(Cursor::new(&jpeg_tables[..jpeg_tables.len() - 2]).chain(reader))
214 as Box<dyn Read>
215 }
216 None => Box::new(reader),
217 };
218
219 let mut decoder = jpeg::Decoder::new(jpeg_reader);
220
221 match photometric_interpretation {
222 PhotometricInterpretation::RGB => decoder.set_color_transform(jpeg::ColorTransform::RGB),
223 PhotometricInterpretation::WhiteIsZero
224 | PhotometricInterpretation::BlackIsZero
225 | PhotometricInterpretation::TransparencyMask => {
226 decoder.set_color_transform(jpeg::ColorTransform::None)
227 }
228 PhotometricInterpretation::CMYK => decoder.set_color_transform(jpeg::ColorTransform::CMYK),
229 PhotometricInterpretation::YCbCr => {
230 decoder.set_color_transform(jpeg::ColorTransform::YCbCr)
231 }
232 photometric_interpretation => {
233 return Err(TiffError::UnsupportedError(
234 TiffUnsupportedError::UnsupportedInterpretation(photometric_interpretation),
235 )
236 .into());
237 }
238 }
239
240 let data = decoder.decode()?;
241 Ok(data)
242}