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
97pub 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
154pub 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 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 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 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 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#[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 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 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 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 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 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
486pub(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 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 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 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 pixbuf = deinterleave2x2(&pixbuf)?;
653 }
654 _ => todo!(),
655 }
656 return Ok(RawImageData::Integer(pixbuf.into_inner()));
657 }
658 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 pixbuf = pixbuf.into_crop(Rect::new(Point::zero(), Dim2::new(tiff_width * cpp, tiff_height)));
684
685 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 let Some(src) = cont {
704 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); 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 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#[derive(Debug, Clone, Default)]
781pub struct RawLoader {
782 cameras: HashMap<(String, String, String), Camera>,
783 #[allow(dead_code)] naked: HashMap<usize, Camera>,
785}
786
787impl RawLoader {
788 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 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 let mut cam = Camera::new();
809 cam.update_from_toml(cammodes[0]);
810 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 (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 pub fn get_cameras(&self) -> &HashMap<(String, String, String), Camera> {
844 &self.cameras
845 }
846
847 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 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 "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 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 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 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 pub fn decode(&self, rawfile: &RawSource, params: &RawDecodeParams, dummy: bool) -> Result<RawImage> {
1033 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 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 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 #[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
1116pub 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
1134pub 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}