Skip to main content

rawler/decoders/
mod.rs

1use chrono::FixedOffset;
2use chrono::NaiveDateTime;
3use chrono::TimeZone;
4use image::DynamicImage;
5use image::ImageBuffer;
6use image::ImageFormat;
7use image::Luma;
8use image::Rgb;
9use log::debug;
10use log::warn;
11use multiversion::multiversion;
12use rayon::iter::IndexedParallelIterator;
13use rayon::iter::ParallelIterator;
14use rayon::prelude::*;
15use rayon::slice::ParallelSliceMut;
16use serde::{Deserialize, Serialize};
17use std::collections::HashMap;
18use std::hash::Hash;
19use std::panic;
20use std::panic::AssertUnwindSafe;
21use std::path::Path;
22use std::rc::Rc;
23use std::str::FromStr;
24use std::sync::Arc;
25use std::time::SystemTime;
26use zerocopy::IntoBytes;
27
28use crate::Result;
29use crate::alloc_image_f32_plain;
30use crate::alloc_image_ok;
31use crate::alloc_image_plain;
32use crate::analyze::FormatDump;
33use crate::bits::LEu32;
34use crate::bits::LookupTable;
35use crate::bits::scale_u16;
36use crate::decompressors::Decompressor;
37use crate::decompressors::LineIteratorMut;
38use crate::decompressors::deflate::DeflateDecompressor;
39use crate::decompressors::jpeg::JpegDecompressor;
40use crate::decompressors::jpeg::LJpegDecompressor;
41use crate::decompressors::jpegxl::JpegXLDecompressor;
42use crate::decompressors::packed::PackedDecompressor;
43use crate::exif::Exif;
44use crate::formats::ciff;
45use crate::formats::jfif;
46use crate::formats::tiff::CompressionMethod;
47use crate::formats::tiff::ExtractFromIFD;
48use crate::formats::tiff::GenericTiffReader;
49use crate::formats::tiff::IFD;
50use crate::formats::tiff::PhotometricInterpretation;
51use crate::formats::tiff::SampleFormat;
52use crate::formats::tiff::Value;
53use crate::formats::tiff::ifd::DataMode;
54use crate::formats::tiff::reader::TiffReader;
55use crate::imgop::Dim2;
56use crate::imgop::Point;
57use crate::imgop::Rect;
58use crate::lens::LensDescription;
59use crate::pixarray::Pix2D;
60use crate::pixarray::PixF32;
61use crate::pixarray::PixU16;
62use crate::pixarray::SubPixel;
63use crate::pixarray::deinterleave2x2;
64use crate::rawsource::RawSource;
65use crate::tags::DngTag;
66
67macro_rules! fetch_ciff_tag {
68  ($tiff:expr, $tag:expr) => {
69    $tiff.find_entry($tag).ok_or(format!("Couldn't find tag {}", stringify!($tag)).to_string())?
70  };
71}
72
73macro_rules! fetch_tiff_tag {
74  ($ifd:expr, $tag:expr) => {
75    $ifd
76      .get_entry($tag)
77      .map(|entry| &entry.value)
78      .ok_or(format!("Couldn't find tag {}", stringify!($tag)))?
79  };
80}
81
82#[allow(unused_macros)]
83macro_rules! fetch_tiff_tag_variant {
84  ($ifd:expr, $tag:expr, $variant:path) => {
85    if let $variant(tmp) = $ifd
86      .get_entry($tag)
87      .map(|entry| &entry.value)
88      .ok_or(format!("Couldn't find tag {}", stringify!($tag)))?
89    {
90      tmp
91    } else {
92      return Err(format!("fetch_tiff_tag_variant!(): tag {} has unepxected datatype", stringify!($tag)).into());
93    }
94  };
95}
96
97/*
98macro_rules! fetch_ifd {
99  ($tiff:expr, $tag:expr) => {
100    $tiff
101      .find_first_ifd($tag)
102      .ok_or(format!("Couldn't find ifd with tag {}", stringify!($tag)).to_string())?
103  };
104}
105 */
106
107pub mod ari;
108pub mod arw;
109mod camera;
110pub mod cr2;
111pub mod cr3;
112pub mod crw;
113pub mod dcr;
114pub mod dcs;
115pub mod dng;
116pub mod erf;
117pub mod iiq;
118pub mod kdc;
119pub mod mef;
120pub mod mos;
121pub mod mrw;
122pub mod nef;
123pub mod nkd;
124pub mod nrw;
125pub mod orf;
126pub mod pef;
127pub mod qtk;
128pub mod raf;
129pub mod rw2;
130pub mod srw;
131pub mod tfr;
132mod unwrapped;
133pub mod x3f;
134
135pub use camera::Camera;
136
137use crate::RawlerError;
138use crate::alloc_image;
139use crate::formats::bmff::Bmff;
140use crate::tags::ExifTag;
141use crate::tags::TiffCommonTag;
142
143pub use super::rawimage::*;
144
145pub static CAMERAS_TOML: &str = include_str!(concat!(env!("OUT_DIR"), "/cameras.toml"));
146pub static SAMPLE: &str = "\nPlease submit samples at https://raw.pixls.us/";
147pub static BUG: &str = "\nPlease file a bug with a sample file at https://github.com/dnglab/dnglab/issues";
148
149const SUPPORTED_FILES_EXT: [&str; 29] = [
150  "ARI", "ARW", "CR2", "CR3", "CRM", "CRW", "DCR", "DCS", "DNG", "ERF", "IIQ", "KDC", "MEF", "MOS", "MRW", "NEF", "NRW", "ORF", "ORI", "PEF", "RAF", "RAW",
151  "RW2", "RWL", "SRW", "3FR", "FFF", "X3F", "QTK",
152];
153
154/// Get list of supported file extensions. All names
155/// are upper-case.
156pub fn supported_extensions() -> &'static [&'static str] {
157  &SUPPORTED_FILES_EXT[..]
158}
159
160pub trait Readable: std::io::Read + std::io::Seek {}
161
162pub type ReadableBoxed = Box<dyn Readable>;
163
164#[derive(Default, Clone, Debug, Hash, Eq, PartialEq)]
165pub struct RawDecodeParams {
166  pub image_index: usize,
167}
168
169#[derive(Default, Debug, Clone)]
170struct DecoderCache<T>
171where
172  T: Default + Clone,
173{
174  cache: Arc<std::sync::RwLock<HashMap<RawDecodeParams, T>>>,
175}
176
177impl<T> DecoderCache<T>
178where
179  T: Default + Clone,
180{
181  fn new() -> Self {
182    Self::default()
183  }
184
185  fn get(&self, params: &RawDecodeParams) -> Option<T> {
186    self.cache.read().expect("DecoderCache is poisoned").get(params).cloned()
187  }
188
189  fn set(&self, params: &RawDecodeParams, value: T) {
190    self.cache.write().expect("DecoderCache is poisoned").insert(params.clone(), value);
191  }
192}
193
194#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
195pub enum WellKnownIFD {
196  Root,
197  Raw,
198  Preview,
199  Exif,
200  ExifGps,
201  VirtualDngRootTags,
202  VirtualDngRawTags,
203}
204
205#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
206pub enum FormatHint {
207  Unknown,
208  CR2,
209  CR3,
210  CRW,
211  NEF,
212  ARW,
213  RAF,
214  RW2,
215  ARI,
216  DNG,
217  DCR,
218  DCS,
219  ERF,
220  IIQ,
221  KDC,
222  MEF,
223  MOS,
224  MRW,
225  NRW,
226  ORF,
227  PEF,
228  QTK,
229  SRW,
230  TFR,
231  X3F,
232}
233
234impl Default for FormatHint {
235  fn default() -> Self {
236    Self::Unknown
237  }
238}
239
240#[derive(Default, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
241pub struct RawMetadata {
242  pub exif: Exif,
243  pub model: String,
244  pub make: String,
245  pub lens: Option<LensDescription>,
246  pub unique_image_id: Option<u128>,
247  pub rating: Option<u32>,
248}
249
250impl RawMetadata {
251  pub(crate) fn new(camera: &Camera, exif: Exif) -> Self {
252    Self {
253      exif,
254      model: camera.clean_model.clone(),
255      make: camera.clean_make.clone(),
256      unique_image_id: None,
257      lens: None,
258      rating: None,
259    }
260  }
261
262  pub(crate) fn new_with_lens(camera: &Camera, mut exif: Exif, lens: Option<LensDescription>) -> Self {
263    if let Some(lens) = &lens {
264      exif.extend_from_lens(lens);
265    }
266    Self {
267      exif,
268      model: camera.clean_model.clone(),
269      make: camera.clean_make.clone(),
270      unique_image_id: None,
271      lens,
272      rating: None,
273    }
274  }
275
276  pub fn last_modified(&self) -> Result<Option<SystemTime>> {
277    let mtime = self
278      .exif
279      .modify_date
280      .as_ref()
281      .map(|mtime| NaiveDateTime::parse_from_str(mtime, "%Y:%m:%d %H:%M:%S"))
282      .transpose()
283      .map_err(|err| RawlerError::DecoderFailed(err.to_string()))?;
284    if let Some(mtime) = mtime {
285      // Probe for available timezone information
286      let tz = if let Some(offset) = self.exif.timezone_offset.as_ref().and_then(|x| x.get(1)) {
287        if let Some(tz) = FixedOffset::east_opt(*offset as i32 * 3600) {
288          Some(tz)
289        } else {
290          log::warn!("TZ Offset overflow");
291          None
292        }
293      } else if let Some(offset) = &self.exif.offset_time {
294        match FixedOffset::from_str(offset) {
295          Ok(tz) => Some(tz),
296          Err(err) => {
297            log::warn!("Invalid fixed offset: {}", err);
298            None
299          }
300        }
301      } else {
302        None
303      };
304      // Any timezone? Then correct...
305      if let Some(tz) = tz {
306        let x = tz
307          .from_local_datetime(&mtime)
308          .earliest()
309          .ok_or(RawlerError::DecoderFailed(format!("Failed to convert datetime to local: {:?}", mtime)))?;
310        return Ok(Some(x.into()));
311      } else {
312        match chrono::Local.from_local_datetime(&mtime).earliest() {
313          Some(ts) => return Ok(Some(ts.into())),
314          None => {
315            log::warn!("Failed to convert ts to local time");
316          }
317        }
318      }
319    }
320
321    Ok(None)
322  }
323}
324
325pub trait Decoder: Send {
326  fn raw_image(&self, file: &RawSource, params: &RawDecodeParams, dummy: bool) -> Result<RawImage>;
327
328  fn raw_image_count(&self) -> Result<usize> {
329    Ok(1)
330  }
331
332  /// Gives the metadata for a Raw. This is not the original data but
333  /// a generalized set of metadata attributes.
334  fn raw_metadata(&self, file: &RawSource, params: &RawDecodeParams) -> Result<RawMetadata>;
335
336  fn xpacket(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result<Option<Vec<u8>>> {
337    Ok(None)
338  }
339
340  fn thumbnail_image(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result<Option<DynamicImage>> {
341    warn!("Decoder has no thumbnail image support, fallback to preview image");
342    Ok(None)
343  }
344
345  // TODO: clarify preview and full image
346  fn preview_image(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result<Option<DynamicImage>> {
347    warn!("Decoder has no preview image support");
348    Ok(None)
349  }
350
351  fn full_image(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result<Option<DynamicImage>> {
352    warn!("Decoder has no full image support");
353    Ok(None)
354  }
355
356  fn format_dump(&self) -> FormatDump;
357
358  fn ifd(&self, _wk_ifd: WellKnownIFD) -> Result<Option<Rc<IFD>>> {
359    Ok(None)
360  }
361
362  fn format_hint(&self) -> FormatHint;
363}
364
365/// Possible orientations of an image
366///
367/// Values are taken from the IFD tag Orientation (0x0112) in most cases but they can be
368/// obtained from other metadata in the file.
369#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)]
370#[allow(missing_docs)]
371pub enum Orientation {
372  Normal,
373  HorizontalFlip,
374  Rotate180,
375  VerticalFlip,
376  Transpose,
377  Rotate90,
378  Transverse,
379  Rotate270,
380  Unknown,
381}
382
383impl Orientation {
384  /// Convert a u16 from the IFD tag Orientation (0x0112) into its corresponding
385  /// enum value
386  pub fn from_u16(orientation: u16) -> Orientation {
387    match orientation {
388      1 => Orientation::Normal,
389      2 => Orientation::HorizontalFlip,
390      3 => Orientation::Rotate180,
391      4 => Orientation::VerticalFlip,
392      5 => Orientation::Transpose,
393      6 => Orientation::Rotate90,
394      7 => Orientation::Transverse,
395      8 => Orientation::Rotate270,
396      _ => Orientation::Unknown,
397    }
398  }
399
400  /// Extract orienation from a TiffIFD. If the given TiffIFD has an invalid
401  /// value or contains no orientation data `Orientation::Unknown` is returned
402  fn from_tiff(tiff: &IFD) -> Orientation {
403    match tiff.get_entry(TiffCommonTag::Orientation) {
404      Some(entry) => Orientation::from_u16(entry.force_usize(0) as u16),
405      None => Orientation::Unknown,
406    }
407  }
408
409  /// Convert orientation to an image flip operation tuple. The first field is
410  /// if x and y coordinates should be swapped (transposed). The second and
411  /// third field is horizontal and vertical flipping respectively. For a
412  /// correct result, flipping must be done before transposing.
413  pub fn to_flips(&self) -> (bool, bool, bool) {
414    match *self {
415      Orientation::Normal | Orientation::Unknown => (false, false, false),
416      Orientation::VerticalFlip => (false, false, true),
417      Orientation::HorizontalFlip => (false, true, false),
418      Orientation::Rotate180 => (false, true, true),
419      Orientation::Transpose => (true, false, false),
420      Orientation::Rotate90 => (true, false, true),
421      Orientation::Rotate270 => (true, true, false),
422      Orientation::Transverse => (true, true, true),
423    }
424  }
425
426  /// Does the opposite of to_flips()
427  pub fn from_flips(flips: (bool, bool, bool)) -> Self {
428    match flips {
429      (false, false, false) => Orientation::Normal,
430      (false, false, true) => Orientation::VerticalFlip,
431      (false, true, false) => Orientation::HorizontalFlip,
432      (false, true, true) => Orientation::Rotate180,
433      (true, false, false) => Orientation::Transpose,
434      (true, false, true) => Orientation::Rotate90,
435      (true, true, false) => Orientation::Rotate270,
436      (true, true, true) => Orientation::Transverse,
437    }
438  }
439
440  /// Convert orientation to the Tiff Orientation value
441  pub fn to_u16(&self) -> u16 {
442    match *self {
443      Orientation::Unknown => 0,
444      Orientation::Normal => 1,
445      Orientation::HorizontalFlip => 2,
446      Orientation::Rotate180 => 3,
447      Orientation::VerticalFlip => 4,
448      Orientation::Transpose => 5,
449      Orientation::Rotate90 => 6,
450      Orientation::Transverse => 7,
451      Orientation::Rotate270 => 8,
452    }
453  }
454}
455
456pub(crate) fn ok_cfa_image(camera: Camera, cpp: usize, wb_coeffs: [f32; 4], image: PixU16, dummy: bool) -> Result<RawImage> {
457  assert_eq!(cpp, 1);
458  Ok(RawImage::new(
459    camera.clone(),
460    image,
461    cpp,
462    wb_coeffs,
463    RawPhotometricInterpretation::Cfa(CFAConfig::new_from_camera(&camera)),
464    None,
465    None,
466    dummy,
467  ))
468}
469
470pub(crate) fn ok_cfa_image_with_blacklevels(camera: Camera, cpp: usize, wb_coeffs: [f32; 4], blacks: [u32; 4], image: PixU16, dummy: bool) -> Result<RawImage> {
471  assert_eq!(cpp, 1);
472  let blacklevel = BlackLevel::new(&blacks, camera.cfa.width, camera.cfa.height, cpp);
473  let img = RawImage::new(
474    camera.clone(),
475    image,
476    cpp,
477    wb_coeffs,
478    RawPhotometricInterpretation::Cfa(CFAConfig::new_from_camera(&camera)),
479    Some(blacklevel),
480    None,
481    dummy,
482  );
483  Ok(img)
484}
485
486/*
487pub(crate) fn ok_cfa_image_with_black_white(camera: Camera, cpp: usize, wb_coeffs: [f32; 4], black: u32, white: u32, image: PixU16, dummy: bool) -> Result<RawImage> {
488  assert_eq!(cpp, 1);
489  let blacklevel = BlackLevel::new(&vec![black; cpp], 1, 1, cpp);
490  let whitelevel = WhiteLevel::new(vec![white; cpp]);
491  let img = RawImage::new(
492    camera.clone(),
493    image,
494    cpp,
495    wb_coeffs,
496    RawPhotometricInterpretation::Cfa(CFAConfig::new_from_camera(&camera)),
497    Some(blacklevel),
498    Some(whitelevel),
499    dummy,
500  );
501  Ok(img)
502}
503   */
504
505pub(crate) fn dynamic_image_from_jpeg_interchange_format(ifd: &IFD, rawsource: &RawSource) -> Result<DynamicImage> {
506  let offset = fetch_tiff_tag!(ifd, ExifTag::JPEGInterchangeFormat).force_usize(0) as u64;
507  let size = fetch_tiff_tag!(ifd, ExifTag::JPEGInterchangeFormatLength).force_usize(0) as u64;
508  let buf = rawsource.subview(offset, size)?;
509  image::load_from_memory_with_format(buf, ImageFormat::Jpeg).map_err(|err| RawlerError::DecoderFailed(format!("Failed to read JPEG image: {:?}", err)))
510}
511
512pub(crate) fn dynamic_image_from_ifd(ifd: &IFD, rawsource: &RawSource) -> Result<DynamicImage> {
513  let tiff_width = fetch_tiff_tag!(ifd, TiffCommonTag::ImageWidth).force_usize(0);
514  let tiff_height = fetch_tiff_tag!(ifd, TiffCommonTag::ImageLength).force_usize(0);
515  let cpp = fetch_tiff_tag!(ifd, TiffCommonTag::SamplesPerPixel).force_usize(0);
516  let bits = fetch_tiff_tag!(ifd, TiffCommonTag::BitsPerSample).force_u32(0);
517  let image = plain_image_from_ifd(ifd, rawsource)?;
518  match image {
519    RawImageData::Integer(samples) => match bits {
520      8 => {
521        let buf: Vec<u8> = samples.into_iter().map(|p| p as u8).collect();
522        match cpp {
523          1 => Ok(DynamicImage::ImageLuma8(
524            ImageBuffer::<Luma<u8>, Vec<u8>>::from_raw(tiff_width as u32, tiff_height as u32, buf.to_vec())
525              .ok_or(RawlerError::DecoderFailed(format!("Create RGB thumbnail from strip failed")))?,
526          )),
527          3 => Ok(DynamicImage::ImageRgb8(
528            ImageBuffer::<Rgb<u8>, Vec<u8>>::from_raw(tiff_width as u32, tiff_height as u32, buf.to_vec())
529              .ok_or(RawlerError::DecoderFailed(format!("Create RGB thumbnail from strip failed")))?,
530          )),
531          _ => unimplemented!(),
532        }
533      }
534      9..=16 => {
535        let samples = if bits == 16 {
536          samples
537        } else {
538          samples.into_par_iter().map(|p| scale_u16(p, bits)).collect()
539        };
540        match cpp {
541          1 => Ok(DynamicImage::ImageLuma16(
542            ImageBuffer::<Luma<u16>, Vec<u16>>::from_raw((tiff_width) as u32, tiff_height as u32, samples)
543              .ok_or(RawlerError::DecoderFailed(format!("Create Y image failed")))?,
544          )),
545          3 => Ok(DynamicImage::ImageRgb16(
546            ImageBuffer::<Rgb<u16>, Vec<u16>>::from_raw((tiff_width) as u32, tiff_height as u32, samples)
547              .ok_or(RawlerError::DecoderFailed(format!("Create RGB image failed")))?,
548          )),
549          _ => unimplemented!(),
550        }
551      }
552      _ => unimplemented!(),
553    },
554    RawImageData::Float(samples) => match cpp {
555      3 => Ok(DynamicImage::ImageRgb32F(
556        // This may not work, rescaling required.
557        ImageBuffer::<Rgb<f32>, Vec<f32>>::from_raw(tiff_width as u32, tiff_height as u32, samples)
558          .ok_or(RawlerError::DecoderFailed(format!("Create RGB image failed")))?,
559      )),
560      _ => unimplemented!(),
561    },
562  }
563}
564
565pub(crate) fn plain_image_from_ifd(ifd: &IFD, rawsource: &RawSource) -> Result<RawImageData> {
566  let endian = ifd.endian;
567  let tiff_width = fetch_tiff_tag!(ifd, TiffCommonTag::ImageWidth).force_usize(0);
568  let tiff_height = fetch_tiff_tag!(ifd, TiffCommonTag::ImageLength).force_usize(0);
569  let cpp = fetch_tiff_tag!(ifd, TiffCommonTag::SamplesPerPixel).force_usize(0);
570  let bits = fetch_tiff_tag!(ifd, TiffCommonTag::BitsPerSample).force_u32(0);
571  let sample_format = SampleFormat::extract(ifd)?.unwrap_or(SampleFormat::Uint);
572  let compression = CompressionMethod::extract(ifd)?.unwrap_or(CompressionMethod::None);
573  let pi = PhotometricInterpretation::extract(ifd)?.unwrap_or(PhotometricInterpretation::BlackIsZero);
574
575  log::debug!(
576    "TIFF image: {}x{}, cpp={}, bits={}, compression={:?}, sample_format={:?}, data_mode={:?}, endian={:?}",
577    tiff_width,
578    tiff_height,
579    cpp,
580    bits,
581    compression,
582    sample_format,
583    ifd.data_mode()?,
584    endian,
585  );
586
587  let (decode_width, decode_height) = match ifd.data_mode()? {
588    DataMode::Strips => (tiff_width, tiff_height),
589    DataMode::Tiles => {
590      let twidth = fetch_tiff_tag!(ifd, TiffCommonTag::TileWidth).force_usize(0);
591      let tlength = fetch_tiff_tag!(ifd, TiffCommonTag::TileLength).force_usize(0);
592      (((tiff_width - 1) / twidth + 1) * twidth, ((tiff_height - 1) / tlength + 1) * tlength)
593    }
594  };
595
596  match sample_format {
597    SampleFormat::Uint => {
598      let mut pixbuf: PixU16 = alloc_image_plain!(decode_width * cpp, decode_height, false);
599      match (compression, ifd.data_mode()?) {
600        (CompressionMethod::None, DataMode::Strips) => {
601          decode_strips::<u16>(&mut pixbuf, rawsource, ifd, PackedDecompressor::new(bits, endian))?;
602        }
603        (CompressionMethod::None, DataMode::Tiles) => {
604          decode_tiles::<u16>(&mut pixbuf, rawsource, ifd, PackedDecompressor::new(bits, endian))?;
605        }
606        (CompressionMethod::ModernJPEG, DataMode::Strips) => {
607          if (pi == PhotometricInterpretation::YCbCr && bits == 8) || (pi == PhotometricInterpretation::BlackIsZero && bits == 8) {
608            decode_strips::<u16>(&mut pixbuf, rawsource, ifd, JpegDecompressor::new())?;
609          } else {
610            decode_strips::<u16>(&mut pixbuf, rawsource, ifd, LJpegDecompressor::new())?;
611          }
612        }
613        (CompressionMethod::ModernJPEG, DataMode::Tiles) => {
614          if (pi == PhotometricInterpretation::YCbCr && bits == 8) || (pi == PhotometricInterpretation::BlackIsZero && bits == 8) {
615            decode_tiles::<u16>(&mut pixbuf, rawsource, ifd, JpegDecompressor::new())?;
616          } else {
617            decode_tiles::<u16>(&mut pixbuf, rawsource, ifd, LJpegDecompressor::new())?;
618          }
619        }
620        (CompressionMethod::LossyJPEG, DataMode::Strips) => {
621          decode_strips::<u16>(&mut pixbuf, rawsource, ifd, JpegDecompressor::new())?;
622        }
623        (CompressionMethod::LossyJPEG, DataMode::Tiles) => {
624          decode_tiles::<u16>(&mut pixbuf, rawsource, ifd, JpegDecompressor::new())?;
625        }
626        (CompressionMethod::JPEGXL, DataMode::Strips) => decode_strips::<u16>(&mut pixbuf, rawsource, ifd, JpegXLDecompressor::new(bits))?,
627        (CompressionMethod::JPEGXL, DataMode::Tiles) => decode_tiles::<u16>(&mut pixbuf, rawsource, ifd, JpegXLDecompressor::new(bits))?,
628        _ => {
629          return Err(RawlerError::DecoderFailed(format!(
630            "Unsupported compression method: {:?}, storage: {:?}",
631            compression,
632            ifd.data_mode()?
633          )));
634        }
635      }
636
637      // We need to crop first, before we do stuff like deinterleaving.
638      // Padded pixels on output by LJPEG compression will corrupt deinterleave.
639      pixbuf = pixbuf.into_crop(Rect::new(Point::zero(), Dim2::new(tiff_width * cpp, tiff_height)));
640
641      if let Some(lintable) = ifd.get_entry(TiffCommonTag::Linearization) {
642        apply_linearization(&mut pixbuf, &lintable.value, bits);
643      }
644
645      // DNG 1.7.1 may store JPEG-XL data in interleaved format
646      let col_ilf = ifd.get_entry(DngTag::ColumnInterleaveFactor).map(|tag| tag.force_u16(0)).unwrap_or(1);
647      let row_ilf = ifd.get_entry(DngTag::RowInterleaveFactor).map(|tag| tag.force_u16(0)).unwrap_or(1);
648      match (row_ilf, col_ilf) {
649        (1, 1) => {}
650        (2, 2) => {
651          // Make sure pixbuf is properly cropped (e.g. LJPEG padding)
652          pixbuf = deinterleave2x2(&pixbuf)?;
653        }
654        _ => todo!(),
655      }
656      return Ok(RawImageData::Integer(pixbuf.into_inner()));
657    }
658    // Floating Point (IEEE) storage
659    SampleFormat::IEEEFP => {
660      let mut pixbuf: PixF32 = alloc_image_f32_plain!(decode_width * cpp, decode_height, false);
661      match (compression, ifd.data_mode()?) {
662        (CompressionMethod::None, DataMode::Strips) => {
663          decode_strips::<f32>(&mut pixbuf, rawsource, ifd, PackedDecompressor::new(bits, endian))?;
664        }
665        (CompressionMethod::None, DataMode::Tiles) => {
666          decode_tiles::<f32>(&mut pixbuf, rawsource, ifd, PackedDecompressor::new(bits, endian))?;
667        }
668        (CompressionMethod::Deflate, DataMode::Tiles) => {
669          let predictor = fetch_tiff_tag!(ifd, TiffCommonTag::Predictor).force_u16(0);
670          decode_tiles::<f32>(&mut pixbuf, rawsource, ifd, DeflateDecompressor::new(cpp, predictor, bits, endian))?;
671        }
672        _ => {
673          return Err(RawlerError::DecoderFailed(format!(
674            "Unsupported compression method: {:?}, storage: {:?}",
675            compression,
676            ifd.data_mode()?
677          )));
678        }
679      }
680
681      // We need to crop first, before we do stuff like deinterleaving.
682      // Padded pixels on output by LJPEG compression will corrupt deinterleave.
683      pixbuf = pixbuf.into_crop(Rect::new(Point::zero(), Dim2::new(tiff_width * cpp, tiff_height)));
684
685      // TODO: other corrections (see u16 code above)?
686
687      return Ok(RawImageData::Float(pixbuf.into_inner()));
688    }
689    _ => unimplemented!("other sample-formats"),
690  }
691}
692
693#[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))]
694pub(super) fn decode_strips<'a, T>(pixbuf: &'a mut Pix2D<T>, file: &RawSource, raw: &IFD, dc: impl Decompressor<'a, T>) -> Result<()>
695where
696  T: SubPixel + 'a,
697{
698  let (strips, cont) = raw.strip_data(file)?;
699  let height = fetch_tiff_tag!(raw, TiffCommonTag::ImageLength).force_usize(0);
700  let rows_per_strip = raw.get_entry(TiffCommonTag::RowsPerStrip).map(|tag| tag.force_usize(0)).unwrap_or(height);
701  let line_width = pixbuf.width;
702  // If we have a continous buffer, we can optimize decompression of multiple strips.
703  if let Some(src) = cont {
704    // Some decompressors performing badly when skip_rows is > 0, because they need to
705    // decompress the skipped rows anyway.
706    if dc.strips_optimized() {
707      decode_threaded_prealloc(pixbuf, &|line, row| dc.decompress(src, row, std::iter::once(line), line_width))?;
708    } else {
709      dc.decompress(src, 0, pixbuf.pixel_rows_mut(), line_width)?;
710    }
711  } else {
712    decode_threaded_multiline_prealloc(pixbuf, rows_per_strip, &|lines, strip, _row| {
713      let src = strips[strip];
714      dc.decompress(src, 0, lines, line_width)
715    })?;
716  }
717
718  Ok(())
719}
720
721#[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))]
722pub(super) fn decode_tiles<'a, T>(pixbuf: &'a mut Pix2D<T>, file: &RawSource, raw: &IFD, dc: impl Decompressor<'a, T>) -> Result<()>
723where
724  T: SubPixel + 'a,
725{
726  use crate::tiles::TilesMut;
727
728  let tiles_src = raw.tile_data(file)?;
729
730  let width = fetch_tiff_tag!(raw, TiffCommonTag::ImageWidth).force_usize(0);
731  let height = fetch_tiff_tag!(raw, TiffCommonTag::ImageLength).force_usize(0);
732  let cpp = fetch_tiff_tag!(raw, TiffCommonTag::SamplesPerPixel).force_usize(0);
733  let twidth = fetch_tiff_tag!(raw, TiffCommonTag::TileWidth).force_usize(0); // * cpp;
734  let tlength = fetch_tiff_tag!(raw, TiffCommonTag::TileLength).force_usize(0);
735  let coltiles = (width - 1) / twidth + 1;
736  let rowtiles = (height - 1) / tlength + 1;
737  if coltiles * rowtiles != tiles_src.len() as usize {
738    return Err(format_args!("DNG: trying to decode {} tiles from {} offsets", coltiles * rowtiles, tiles_src.len()).into());
739  }
740
741  let tiles = pixbuf
742    .data
743    .into_tiles_iter_mut(pixbuf.width / cpp, cpp, twidth, tlength)
744    .map_err(|_| RawlerError::DecoderFailed(format!("Unable to divide source image into tiles")))?;
745
746  let line_width = twidth * cpp;
747  tiles
748    .enumerate()
749    .par_bridge()
750    .map(|(tile_id, tile)| {
751      //eprintln!("Decode tile id {}", tile_id);
752      dc.decompress(tiles_src[tile_id], 0, tile.into_iter_mut(), line_width)
753    })
754    .collect::<std::result::Result<Vec<()>, _>>()?;
755
756  Ok(())
757}
758
759pub(crate) fn apply_linearization(image: &mut PixU16, tbl: &Value, bits: u32) {
760  match tbl {
761    Value::Short(points) => {
762      if points.is_empty() {
763        return;
764      }
765      let table = LookupTable::new_with_bits(points, bits);
766      image.par_pixel_rows_mut().for_each(|row| {
767        let mut random = LEu32(row.as_bytes(), 0);
768        row.iter_mut().for_each(|p| {
769          *p = table.dither(*p, &mut random);
770        })
771      });
772    }
773    _ => {
774      panic!("Unsupported linear table");
775    }
776  }
777}
778
779/// The struct that holds all the info about the cameras and is able to decode a file
780#[derive(Debug, Clone, Default)]
781pub struct RawLoader {
782  cameras: HashMap<(String, String, String), Camera>,
783  #[allow(dead_code)] // TODO: remove once naked cams supported again
784  naked: HashMap<usize, Camera>,
785}
786
787impl RawLoader {
788  /// Creates a new raw loader using the camera information included in the library
789  pub fn new() -> RawLoader {
790    let toml = match CAMERAS_TOML.parse::<toml::Value>() {
791      Ok(val) => val,
792      Err(e) => panic!("{}", format!("Error parsing cameras.toml: {:?}", e)),
793    };
794
795    let mut cams = Vec::new();
796    for camera in toml.get("cameras").unwrap().as_array().unwrap() {
797      // Create a list of all the camera modes including the base one
798      let mut cammodes = Vec::new();
799      let ct = camera.as_table().unwrap();
800      cammodes.push(ct);
801      if let Some(val) = ct.get("modes") {
802        for mode in val.as_array().unwrap() {
803          cammodes.push(mode.as_table().unwrap());
804        }
805      }
806
807      // Start with the basic camera
808      let mut cam = Camera::new();
809      cam.update_from_toml(cammodes[0]);
810      // Create a list of alias names including the base one
811      let mut camnames = vec![(cam.model.clone(), cam.clean_model.clone())];
812      if let Some(val) = ct.get("model_aliases") {
813        for alias in val.as_array().unwrap() {
814          camnames.push((alias[0].as_str().unwrap().to_string().clone(), alias[1].as_str().unwrap().to_string().clone()));
815        }
816      }
817
818      // For each combination of alias and mode (including the base ones) create Camera
819      for (model, clean_model) in camnames {
820        for ct in cammodes.clone() {
821          let mut mcam = cam.clone();
822          mcam.update_from_toml(ct);
823          mcam.model = model.clone();
824          mcam.clean_model = clean_model.clone();
825          cams.push(mcam);
826        }
827      }
828    }
829
830    let mut map = HashMap::new();
831    let mut naked = HashMap::new();
832    for cam in cams {
833      map.insert((cam.make.clone(), cam.model.clone(), cam.mode.clone()), cam.clone());
834      if cam.filesize > 0 {
835        naked.insert(cam.filesize, cam);
836      }
837    }
838
839    RawLoader { cameras: map, naked }
840  }
841
842  /// Get list of cameras
843  pub fn get_cameras(&self) -> &HashMap<(String, String, String), Camera> {
844    &self.cameras
845  }
846
847  /// Returns a decoder for a given buffer
848  pub fn get_decoder<'b>(&'b self, rawfile: &RawSource) -> Result<Box<dyn Decoder + 'b>> {
849    if mrw::is_mrw(rawfile) {
850      let dec = Box::new(mrw::MrwDecoder::new(rawfile, self)?);
851      return Ok(dec as Box<dyn Decoder>);
852    }
853
854    if raf::is_raf(rawfile) {
855      let dec = Box::new(raf::RafDecoder::new(rawfile, self)?);
856      return Ok(dec as Box<dyn Decoder>);
857    }
858
859    if ari::is_ari(rawfile) {
860      let dec = Box::new(ari::AriDecoder::new(rawfile, self)?);
861      return Ok(dec as Box<dyn Decoder>);
862    }
863
864    if qtk::is_qtk(rawfile) {
865      let dec = Box::new(qtk::QtkDecoder::new(rawfile, self)?);
866      return Ok(dec as Box<dyn Decoder>);
867    }
868
869    if ciff::is_ciff(rawfile) {
870      let dec = Box::new(crw::CrwDecoder::new(rawfile, self)?);
871      return Ok(dec as Box<dyn Decoder>);
872    }
873
874    if jfif::is_exif(rawfile) {
875      let exif = jfif::Jfif::new(rawfile)?;
876      if let Some(make) = exif
877        .exif_ifd()
878        .and_then(|ifd| ifd.get_entry(TiffCommonTag::Make))
879        .and_then(|entry| entry.value.as_string().map(|s| s.as_str().trim_end()))
880      {
881        match make {
882          "Konica Minolta Photo Imaging, Inc." => {
883            let dec = Box::new(mrw::MrwDecoder::new_jfif(rawfile, exif, self)?);
884            return Ok(dec as Box<dyn Decoder>);
885          }
886          _ => {
887            log::warn!("Unknown make for EXIF file: {}", make);
888          }
889        }
890      }
891    }
892
893    if x3f::is_x3f(rawfile) {
894      let dec = Box::new(x3f::X3fDecoder::new(rawfile, self)?);
895      return Ok(dec as Box<dyn Decoder>);
896    }
897
898    match Bmff::new(&mut rawfile.reader()) {
899      Ok(bmff) => {
900        if bmff.compatible_brand("crx ") {
901          return Ok(Box::new(cr3::Cr3Decoder::new(rawfile, bmff, self)?));
902        }
903      }
904      Err(e) => {
905        debug!("It's not a BMFF file: {:?}", e);
906      }
907    }
908
909    match GenericTiffReader::new(&mut rawfile.reader(), 0, 0, None, &[]) {
910      Ok(tiff) => {
911        debug!("File is a TIFF file!");
912
913        macro_rules! use_decoder {
914          ($dec:ty, $buf:ident, $tiff:ident, $rawdec:ident) => {
915            Ok(Box::new(<$dec>::new(rawfile, $tiff, $rawdec)?) as Box<dyn Decoder>)
916          };
917        }
918
919        if tiff.has_entry(DngTag::DNGVersion) {
920          return Ok(Box::new(dng::DngDecoder::new(rawfile, tiff, self)?));
921        }
922
923        // The DCS560C is really a CR2 camera so we just special case it here
924        if let Some(model) = tiff.get_entry(TiffCommonTag::Model) {
925          if model.get_string().ok() == Some(&String::from("DCS560C")) {
926            return use_decoder!(cr2::Cr2Decoder, rawfile, tiff, self);
927          }
928        }
929
930        if let Some(make) = tiff
931          .get_entry(TiffCommonTag::Make)
932          .and_then(|entry| entry.value.as_string().map(|s| s.as_str().trim_end()))
933        {
934          match make {
935            "Canon" => return use_decoder!(cr2::Cr2Decoder, rawfile, tiff, self),
936            "PENTAX" => return use_decoder!(pef::PefDecoder, rawfile, tiff, self),
937            "PENTAX Corporation" => return use_decoder!(pef::PefDecoder, rawfile, tiff, self),
938            "RICOH IMAGING COMPANY, LTD." => return use_decoder!(pef::PefDecoder, rawfile, tiff, self),
939            "Phase One" => return use_decoder!(iiq::IiqDecoder, rawfile, tiff, self),
940            "Phase One A/S" => return use_decoder!(iiq::IiqDecoder, rawfile, tiff, self),
941            "Leaf" => return use_decoder!(iiq::IiqDecoder, rawfile, tiff, self),
942            "Hasselblad" => return use_decoder!(tfr::TfrDecoder, rawfile, tiff, self),
943            "SONY" => return use_decoder!(arw::ArwDecoder, rawfile, tiff, self),
944            "Mamiya-OP Co.,Ltd." => return use_decoder!(mef::MefDecoder, rawfile, tiff, self),
945            "OLYMPUS IMAGING CORP." => return use_decoder!(orf::OrfDecoder, rawfile, tiff, self),
946            "OLYMPUS CORPORATION" => return use_decoder!(orf::OrfDecoder, rawfile, tiff, self),
947            "OLYMPUS OPTICAL CO.,LTD" => return use_decoder!(orf::OrfDecoder, rawfile, tiff, self),
948            "OM Digital Solutions" => return use_decoder!(orf::OrfDecoder, rawfile, tiff, self),
949            "SAMSUNG" => return use_decoder!(srw::SrwDecoder, rawfile, tiff, self),
950            "SEIKO EPSON CORP." => return use_decoder!(erf::ErfDecoder, rawfile, tiff, self),
951            "EASTMAN KODAK COMPANY" => return use_decoder!(kdc::KdcDecoder, rawfile, tiff, self),
952            "Eastman Kodak Company" => return use_decoder!(kdc::KdcDecoder, rawfile, tiff, self),
953            "KODAK" => return use_decoder!(dcs::DcsDecoder, rawfile, tiff, self),
954            "Kodak" => return use_decoder!(dcr::DcrDecoder, rawfile, tiff, self),
955            "Panasonic" => return use_decoder!(rw2::Rw2Decoder, rawfile, tiff, self),
956            "LEICA" => return use_decoder!(rw2::Rw2Decoder, rawfile, tiff, self),
957            "LEICA CAMERA AG" => return use_decoder!(rw2::Rw2Decoder, rawfile, tiff, self),
958            //"FUJIFILM" => return use_decoder!(raf::RafDecoder, rawfile, tiff, self),
959            "NIKON" => return use_decoder!(nrw::NrwDecoder, rawfile, tiff, self),
960            "Nikon" => return use_decoder!(nef::NefDecoder, rawfile, tiff, self),
961            "NIKON CORPORATION" => return use_decoder!(nef::NefDecoder, rawfile, tiff, self),
962            x => {
963              return Err(RawlerError::Unsupported {
964                what: format!("Couldn't find a decoder for make \"{}\"", x),
965                make: make.to_string(),
966                model: tiff
967                  .get_entry(TiffCommonTag::Model)
968                  .and_then(|entry| entry.as_string().cloned())
969                  .unwrap_or_default(),
970                mode: String::new(),
971              });
972            }
973          }
974        }
975
976        if tiff.has_entry(TiffCommonTag::Software) {
977          // Last ditch effort to identify Leaf cameras without Make and Model
978          if fetch_tiff_tag!(tiff, TiffCommonTag::Software).as_string() == Some(&"Camera Library".to_string()) {
979            return use_decoder!(mos::MosDecoder, rawfile, tiff, self);
980          }
981        }
982      }
983      Err(e) => {
984        debug!("File is not a tiff file: {:?}", e);
985      }
986    }
987
988    // If all else fails see if we match by filesize to one of those CHDK style files
989    let data = rawfile.as_vec()?;
990    if let Some(cam) = self.naked.get(&data.len()) {
991      return Ok(Box::new(nkd::NakedDecoder::new(cam.clone(), self)?));
992    }
993
994    Err(RawlerError::Unsupported {
995      what: String::from("No decoder found"),
996      model: "".to_string(),
997      make: "".to_string(),
998      mode: "".to_string(),
999    })
1000  }
1001
1002  /// Check support
1003  fn check_supported_with_everything<'a>(&'a self, make: &str, model: &str, mode: &str) -> Result<Camera> {
1004    match self.cameras.get(&(make.to_string(), model.to_string(), mode.to_string())) {
1005      Some(cam) => Ok(cam.clone()),
1006      None => Err(RawlerError::Unsupported {
1007        what: String::from("Unknown camera"),
1008        model: model.to_string(),
1009        make: make.to_string(),
1010        mode: mode.to_string(),
1011      }),
1012    }
1013  }
1014
1015  fn check_supported_with_mode(&self, ifd0: &IFD, mode: &str) -> Result<Camera> {
1016    let make = fetch_tiff_tag!(ifd0, TiffCommonTag::Make).get_string()?.trim_end();
1017    let model = fetch_tiff_tag!(ifd0, TiffCommonTag::Model).get_string()?.trim_end();
1018    self.check_supported_with_everything(make, model, mode)
1019  }
1020
1021  #[allow(dead_code)]
1022  fn check_supported(&self, ifd0: &IFD) -> Result<Camera> {
1023    self.check_supported_with_mode(ifd0, "")
1024  }
1025
1026  fn decode_unsafe(&self, rawfile: &RawSource, params: &RawDecodeParams, dummy: bool) -> Result<RawImage> {
1027    let decoder = self.get_decoder(rawfile)?;
1028    decoder.raw_image(rawfile, params, dummy)
1029  }
1030
1031  /// Decodes an input into a RawImage
1032  pub fn decode(&self, rawfile: &RawSource, params: &RawDecodeParams, dummy: bool) -> Result<RawImage> {
1033    //let buffer = Buffer::new(reader)?;
1034
1035    match panic::catch_unwind(AssertUnwindSafe(|| self.decode_unsafe(rawfile, params, dummy))) {
1036      Ok(val) => val,
1037      Err(_) => Err(RawlerError::DecoderFailed(format!("Caught a panic while decoding.{}", BUG))),
1038    }
1039  }
1040
1041  /// Decodes a file into a RawImage
1042  pub fn decode_file(&self, path: &Path) -> Result<RawImage> {
1043    let rawfile = RawSource::new(path)?;
1044    self.decode(&rawfile, &RawDecodeParams::default(), false)
1045  }
1046
1047  /// Decodes a file into a RawImage
1048  pub fn raw_image_count_file(&self, path: &Path) -> Result<usize> {
1049    let rawfile = RawSource::new(path).map_err(|err| RawlerError::with_io_error("raw_image_count_file()", path, err))?;
1050    let decoder = self.get_decoder(&rawfile)?;
1051    decoder.raw_image_count()
1052  }
1053
1054  // Decodes an unwrapped input (just the image data with minimal metadata) into a RawImage
1055  // This is only useful for fuzzing really
1056  #[doc(hidden)]
1057  pub fn decode_unwrapped(&self, rawfile: &RawSource) -> Result<RawImageData> {
1058    match panic::catch_unwind(AssertUnwindSafe(|| unwrapped::decode_unwrapped(rawfile))) {
1059      Ok(val) => val,
1060      Err(_) => Err(RawlerError::DecoderFailed(format!("Caught a panic while decoding.{}", BUG))),
1061    }
1062  }
1063}
1064
1065pub fn decode_unthreaded<F>(width: usize, height: usize, dummy: bool, closure: &F) -> PixU16
1066where
1067  F: Fn(&mut [u16], usize) + Sync,
1068{
1069  let mut out: PixU16 = alloc_image!(width, height, dummy);
1070  out.pixels_mut().chunks_exact_mut(width).enumerate().for_each(|(row, line)| {
1071    closure(line, row);
1072  });
1073  out
1074}
1075
1076pub fn decode_threaded<F>(width: usize, height: usize, dummy: bool, closure: &F) -> PixU16
1077where
1078  F: Fn(&mut [u16], usize) + Sync,
1079{
1080  let mut out: PixU16 = alloc_image!(width, height, dummy);
1081  out.pixels_mut().par_chunks_exact_mut(width).enumerate().for_each(|(row, line)| {
1082    closure(line, row);
1083  });
1084  out
1085}
1086
1087pub fn decode_threaded_prealloc<'a, T, F>(pixbuf: &'a mut Pix2D<T>, closure: &F) -> std::result::Result<(), String>
1088where
1089  F: Fn(&'a mut [T], usize) -> std::result::Result<(), String> + Sync,
1090  T: SubPixel + 'a,
1091{
1092  let width = pixbuf.width;
1093  pixbuf
1094    .pixels_mut()
1095    .par_chunks_exact_mut(width)
1096    .enumerate()
1097    .map(|(row, line)| closure(line, row))
1098    .collect::<std::result::Result<Vec<()>, _>>()?;
1099  Ok(())
1100}
1101
1102pub fn decode_threaded_multiline<F>(width: usize, height: usize, lines: usize, dummy: bool, closure: &F) -> std::result::Result<PixU16, String>
1103where
1104  F: Fn(&mut [u16], usize) -> std::result::Result<(), String> + Sync,
1105{
1106  let mut out: PixU16 = alloc_image_ok!(width, height, dummy);
1107  out
1108    .pixels_mut()
1109    .par_chunks_mut(width * lines)
1110    .enumerate()
1111    .map(|(row, line)| closure(line, row * lines))
1112    .collect::<std::result::Result<Vec<()>, _>>()?;
1113  Ok(out)
1114}
1115
1116/// Split pixbuf by `lines`.
1117/// Caution: The last chunk may not be equal to `lines`.
1118pub fn decode_threaded_multiline_prealloc<'a, T, F>(pixbuf: &'a mut Pix2D<T>, lines: usize, closure: &F) -> std::result::Result<(), String>
1119where
1120  F: Fn(&mut dyn LineIteratorMut<'a, T>, usize, usize) -> std::result::Result<(), String> + Sync,
1121  T: SubPixel + 'a,
1122{
1123  let width = pixbuf.width;
1124  let chunksize = pixbuf.width * lines;
1125  pixbuf
1126    .pixels_mut()
1127    .par_chunks_mut(chunksize)
1128    .enumerate()
1129    .map(|(strip, chunk)| closure(&mut chunk.chunks_exact_mut(width), strip, strip * lines))
1130    .collect::<std::result::Result<Vec<()>, _>>()?;
1131  Ok(())
1132}
1133
1134/// This is used for streams where not chunked at line boundaries.
1135pub fn decode_threaded_chunked<F>(width: usize, height: usize, chunksize: usize, dummy: bool, closure: &F) -> PixU16
1136where
1137  F: Fn(&mut [u16], usize) + Sync,
1138{
1139  let mut out: PixU16 = alloc_image!(width, height, dummy);
1140  out.pixels_mut().par_chunks_mut(chunksize).enumerate().for_each(|(chunk_id, chunk)| {
1141    closure(chunk, chunk_id);
1142  });
1143  out
1144}