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::{AsyncTiffError, AsyncTiffResult, TiffError, TiffUnsupportedError};
11use crate::tags::{Compression, PhotometricInterpretation};
12
13#[derive(Debug)]
28pub struct DecoderRegistry(HashMap<Compression, Box<dyn Decoder>>);
29
30impl DecoderRegistry {
31 pub fn empty() -> Self {
33 Self(HashMap::new())
34 }
35}
36
37impl AsRef<HashMap<Compression, Box<dyn Decoder>>> for DecoderRegistry {
38 fn as_ref(&self) -> &HashMap<Compression, Box<dyn Decoder>> {
39 &self.0
40 }
41}
42
43impl AsMut<HashMap<Compression, Box<dyn Decoder>>> for DecoderRegistry {
44 fn as_mut(&mut self) -> &mut HashMap<Compression, 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(Compression::None, Box::new(UncompressedDecoder) as _);
53 registry.insert(Compression::Deflate, Box::new(DeflateDecoder) as _);
54 registry.insert(Compression::OldDeflate, Box::new(DeflateDecoder) as _);
55 #[cfg(feature = "lerc")]
56 registry.insert(Compression::LERC, Box::new(LercDecoder) as _);
57 #[cfg(feature = "lzma")]
58 registry.insert(Compression::LZMA, Box::new(LZMADecoder) as _);
59 registry.insert(Compression::LZW, Box::new(LZWDecoder) as _);
60 registry.insert(Compression::ModernJPEG, Box::new(JPEGDecoder) as _);
61 #[cfg(feature = "jpeg2k")]
62 registry.insert(Compression::JPEG2k, Box::new(JPEG2kDecoder) as _);
63 #[cfg(feature = "webp")]
64 registry.insert(Compression::WebP, Box::new(WebPDecoder) as _);
65 registry.insert(Compression::ZSTD, Box::new(ZstdDecoder) as _);
66 Self(registry)
67 }
68}
69
70pub trait Decoder: Debug + Send + Sync {
72 fn decode_tile(
74 &self,
75 buffer: Bytes,
76 photometric_interpretation: PhotometricInterpretation,
77 jpeg_tables: Option<&[u8]>,
78 samples_per_pixel: u16,
79 bits_per_sample: u16,
80 lerc_parameters: Option<&[u32]>,
81 ) -> AsyncTiffResult<Vec<u8>>;
82}
83
84#[derive(Debug, Clone)]
86pub struct DeflateDecoder;
87
88impl Decoder for DeflateDecoder {
89 fn decode_tile(
90 &self,
91 buffer: Bytes,
92 _photometric_interpretation: PhotometricInterpretation,
93 _jpeg_tables: Option<&[u8]>,
94 _samples_per_pixel: u16,
95 _bits_per_sample: u16,
96 _lerc_parameters: Option<&[u32]>,
97 ) -> AsyncTiffResult<Vec<u8>> {
98 let mut decoder = ZlibDecoder::new(Cursor::new(buffer));
99 let mut buf = Vec::new();
100 decoder.read_to_end(&mut buf)?;
101 Ok(buf)
102 }
103}
104
105#[derive(Debug, Clone)]
107pub struct JPEGDecoder;
108
109impl Decoder for JPEGDecoder {
110 fn decode_tile(
111 &self,
112 buffer: Bytes,
113 photometric_interpretation: PhotometricInterpretation,
114 jpeg_tables: Option<&[u8]>,
115 _samples_per_pixel: u16,
116 _bits_per_sample: u16,
117 _lerc_parameters: Option<&[u32]>,
118 ) -> AsyncTiffResult<Vec<u8>> {
119 decode_modern_jpeg(buffer, photometric_interpretation, jpeg_tables)
120 }
121}
122
123#[cfg(feature = "lerc")]
125#[derive(Debug, Clone)]
126pub struct LercDecoder;
127
128#[cfg(feature = "lerc")]
130fn decode_lerc<T: lerc::LercDataType + bytemuck::Pod>(
131 buffer: &[u8],
132 info: &lerc::BlobInfo,
133) -> AsyncTiffResult<Vec<u8>> {
134 let (data, _mask) = lerc::decode::<T>(
135 buffer,
136 info.width as usize,
137 info.height as usize,
138 info.depth as usize,
139 info.bands as usize,
140 info.masks as usize,
141 )
142 .map_err(|e| AsyncTiffError::General(format!("LERC decode failed: {e}")))?;
143
144 Ok(bytemuck::cast_slice(&data).to_vec())
147}
148
149#[cfg(feature = "lerc")]
150impl Decoder for LercDecoder {
151 fn decode_tile(
152 &self,
153 buffer: Bytes,
154 _photometric_interpretation: PhotometricInterpretation,
155 _jpeg_tables: Option<&[u8]>,
156 _samples_per_pixel: u16,
157 _bits_per_sample: u16,
158 lerc_parameters: Option<&[u32]>,
159 ) -> AsyncTiffResult<Vec<u8>> {
160 let lerc_blob: Vec<u8> = match lerc_parameters.and_then(|p| p.get(1).copied()) {
164 Some(1) => {
165 let mut decoder = ZlibDecoder::new(Cursor::new(buffer));
166 let mut buf = Vec::new();
167 decoder.read_to_end(&mut buf)?;
168 buf
169 }
170 Some(2) => {
171 let mut decoder = zstd::Decoder::new(Cursor::new(buffer))?;
172 let mut buf = Vec::new();
173 decoder.read_to_end(&mut buf)?;
174 buf
175 }
176 _ => buffer.to_vec(),
177 };
178
179 let info = lerc::get_blob_info(&lerc_blob)
180 .map_err(|e| AsyncTiffError::General(format!("LERC get_blob_info failed: {e}")))?;
181
182 match info.data_type {
185 0 => decode_lerc::<i8>(&lerc_blob, &info),
186 1 => decode_lerc::<u8>(&lerc_blob, &info),
187 2 => decode_lerc::<i16>(&lerc_blob, &info),
188 3 => decode_lerc::<u16>(&lerc_blob, &info),
189 4 => decode_lerc::<i32>(&lerc_blob, &info),
190 5 => decode_lerc::<u32>(&lerc_blob, &info),
191 6 => decode_lerc::<f32>(&lerc_blob, &info),
192 7 => decode_lerc::<f64>(&lerc_blob, &info),
193 _ => Err(AsyncTiffError::General(format!(
194 "Unsupported LERC data type: {}",
195 info.data_type
196 ))),
197 }
198 }
199}
200
201#[derive(Debug, Clone)]
203#[cfg(feature = "lzma")]
204pub struct LZMADecoder;
205
206#[cfg(feature = "lzma")]
207impl Decoder for LZMADecoder {
208 fn decode_tile(
209 &self,
210 buffer: Bytes,
211 _photometric_interpretation: PhotometricInterpretation,
212 _jpeg_tables: Option<&[u8]>,
213 _samples_per_pixel: u16,
214 _bits_per_sample: u16,
215 _lerc_parameters: Option<&[u32]>,
216 ) -> AsyncTiffResult<Vec<u8>> {
217 use bytes::Buf;
218 use lzma_rust2::XzReader;
219
220 let mut reader = XzReader::new(buffer.reader(), false);
221 let mut out = Vec::new();
222 reader.read_to_end(&mut out)?;
223 Ok(out)
224 }
225}
226
227#[derive(Debug, Clone)]
229pub struct LZWDecoder;
230
231impl Decoder for LZWDecoder {
232 fn decode_tile(
233 &self,
234 buffer: Bytes,
235 _photometric_interpretation: PhotometricInterpretation,
236 _jpeg_tables: Option<&[u8]>,
237 _samples_per_pixel: u16,
238 _bits_per_sample: u16,
239 _lerc_parameters: Option<&[u32]>,
240 ) -> AsyncTiffResult<Vec<u8>> {
241 let mut decoder = weezl::decode::Decoder::with_tiff_size_switch(weezl::BitOrder::Msb, 8);
243 let decoded = decoder.decode(&buffer).expect("failed to decode LZW data");
244 Ok(decoded)
245 }
246}
247
248#[cfg(feature = "jpeg2k")]
250#[derive(Debug, Clone)]
251pub struct JPEG2kDecoder;
252
253#[cfg(feature = "jpeg2k")]
254impl Decoder for JPEG2kDecoder {
255 fn decode_tile(
256 &self,
257 buffer: Bytes,
258 _photometric_interpretation: PhotometricInterpretation,
259 _jpeg_tables: Option<&[u8]>,
260 _samples_per_pixel: u16,
261 _bits_per_sample: u16,
262 _lerc_parameters: Option<&[u32]>,
263 ) -> AsyncTiffResult<Vec<u8>> {
264 let decoder = jpeg2k::DecodeParameters::new();
265
266 let image = jpeg2k::Image::from_bytes_with(&buffer, decoder)?;
267
268 let id = image.get_pixels(None)?;
269 match id.data {
270 jpeg2k::ImagePixelData::L8(items)
271 | jpeg2k::ImagePixelData::La8(items)
272 | jpeg2k::ImagePixelData::Rgb8(items)
273 | jpeg2k::ImagePixelData::Rgba8(items) => Ok(items),
274 jpeg2k::ImagePixelData::L16(items)
275 | jpeg2k::ImagePixelData::La16(items)
276 | jpeg2k::ImagePixelData::Rgb16(items)
277 | jpeg2k::ImagePixelData::Rgba16(items) => Ok(bytemuck::cast_vec(items)),
278 }
279 }
280}
281
282#[cfg(feature = "webp")]
284#[derive(Debug, Clone)]
285pub struct WebPDecoder;
286
287#[cfg(feature = "webp")]
288impl Decoder for WebPDecoder {
289 fn decode_tile(
290 &self,
291 buffer: Bytes,
292 _photometric_interpretation: PhotometricInterpretation,
293 _jpeg_tables: Option<&[u8]>,
294 samples_per_pixel: u16,
295 bits_per_sample: u16,
296 _lerc_parameters: Option<&[u32]>,
297 ) -> AsyncTiffResult<Vec<u8>> {
298 let decoded = webp::Decoder::new(&buffer)
299 .decode()
300 .ok_or(AsyncTiffError::General("WebP decoding failed".to_string()))?;
301
302 let data = decoded.to_vec();
303
304 if samples_per_pixel == 4 && bits_per_sample == 8 && !decoded.is_alpha() {
308 let mut rgba = Vec::with_capacity(data.len() / 3 * 4);
309 for chunk in data.chunks_exact(3) {
310 rgba.extend_from_slice(chunk);
311 rgba.push(255); }
313 Ok(rgba)
314 } else {
315 Ok(data)
316 }
317 }
318}
319
320#[derive(Debug, Clone)]
322pub struct UncompressedDecoder;
323
324impl Decoder for UncompressedDecoder {
325 fn decode_tile(
326 &self,
327 buffer: Bytes,
328 _photometric_interpretation: PhotometricInterpretation,
329 _jpeg_tables: Option<&[u8]>,
330 _samples_per_pixel: u16,
331 _bits_per_sample: u16,
332 _lerc_parameters: Option<&[u32]>,
333 ) -> AsyncTiffResult<Vec<u8>> {
334 Ok(buffer.to_vec())
335 }
336}
337
338#[derive(Debug, Clone)]
340pub struct ZstdDecoder;
341
342impl Decoder for ZstdDecoder {
343 fn decode_tile(
344 &self,
345 buffer: Bytes,
346 _photometric_interpretation: PhotometricInterpretation,
347 _jpeg_tables: Option<&[u8]>,
348 _samples_per_pixel: u16,
349 _bits_per_sample: u16,
350 _lerc_parameters: Option<&[u32]>,
351 ) -> AsyncTiffResult<Vec<u8>> {
352 let mut decoder = zstd::Decoder::new(Cursor::new(buffer))?;
353 let mut buf = Vec::new();
354 decoder.read_to_end(&mut buf)?;
355 Ok(buf)
356 }
357}
358
359fn decode_modern_jpeg(
361 buf: Bytes,
362 photometric_interpretation: PhotometricInterpretation,
363 jpeg_tables: Option<&[u8]>,
364) -> AsyncTiffResult<Vec<u8>> {
365 let reader = Cursor::new(buf);
376
377 let jpeg_reader = match jpeg_tables {
378 Some(jpeg_tables) => {
379 let mut reader = reader;
380 reader.read_exact(&mut [0; 2])?;
381
382 Box::new(Cursor::new(&jpeg_tables[..jpeg_tables.len() - 2]).chain(reader))
383 as Box<dyn Read>
384 }
385 None => Box::new(reader),
386 };
387
388 let mut decoder = jpeg::Decoder::new(jpeg_reader);
389
390 match photometric_interpretation {
391 PhotometricInterpretation::RGB => decoder.set_color_transform(jpeg::ColorTransform::RGB),
392 PhotometricInterpretation::WhiteIsZero
393 | PhotometricInterpretation::BlackIsZero
394 | PhotometricInterpretation::TransparencyMask => {
395 decoder.set_color_transform(jpeg::ColorTransform::None)
396 }
397 PhotometricInterpretation::CMYK => decoder.set_color_transform(jpeg::ColorTransform::CMYK),
398 PhotometricInterpretation::YCbCr => {
399 decoder.set_color_transform(jpeg::ColorTransform::YCbCr)
400 }
401 photometric_interpretation => {
402 return Err(TiffError::UnsupportedError(
403 TiffUnsupportedError::UnsupportedInterpretation(photometric_interpretation),
404 )
405 .into());
406 }
407 }
408
409 let data = decoder.decode()?;
410 Ok(data)
411}