Vendor rawler 0.7.2 unmodified
The crate as crates.io publishes it, minus .cargo-ok, its Cargo.lock and data/testdata (13 MB of sample files only its own tests read). Not yet routed through [patch.crates-io]; the next commit is the patch.
This commit is contained in:
+113
@@ -0,0 +1,113 @@
|
||||
use log::warn;
|
||||
|
||||
use crate::RawlerError;
|
||||
use crate::analyze::FormatDump;
|
||||
use crate::rawsource::RawSource;
|
||||
|
||||
use crate::RawImage;
|
||||
use crate::RawLoader;
|
||||
use crate::Result;
|
||||
use crate::bits::BEu16;
|
||||
use crate::exif::Exif;
|
||||
use crate::formats::tiff::GenericTiffReader;
|
||||
use crate::formats::tiff::IFD;
|
||||
use crate::formats::tiff::ifd::OffsetMode;
|
||||
use crate::formats::tiff::reader::TiffReader;
|
||||
use crate::packed::decode_12be_wcontrol;
|
||||
use crate::tags::ExifTag;
|
||||
use crate::tags::TiffCommonTag;
|
||||
|
||||
use super::BlackLevel;
|
||||
use super::CFAConfig;
|
||||
use super::Camera;
|
||||
use super::Decoder;
|
||||
use super::FormatHint;
|
||||
use super::RawDecodeParams;
|
||||
use super::RawMetadata;
|
||||
use super::RawPhotometricInterpretation;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ErfDecoder<'a> {
|
||||
#[allow(unused)]
|
||||
rawloader: &'a RawLoader,
|
||||
tiff: GenericTiffReader,
|
||||
makernote: IFD,
|
||||
camera: Camera,
|
||||
}
|
||||
|
||||
impl<'a> ErfDecoder<'a> {
|
||||
pub fn new(file: &RawSource, tiff: GenericTiffReader, rawloader: &'a RawLoader) -> Result<ErfDecoder<'a>> {
|
||||
let camera = rawloader.check_supported(tiff.root_ifd())?;
|
||||
|
||||
let makernote = if let Some(exif) = tiff.find_first_ifd_with_tag(ExifTag::MakerNotes) {
|
||||
exif.parse_makernote(&mut file.reader(), OffsetMode::Absolute, &[])?
|
||||
} else {
|
||||
warn!("ERF makernote not found");
|
||||
None
|
||||
}
|
||||
.ok_or("File has not makernotes")?;
|
||||
|
||||
Ok(ErfDecoder {
|
||||
tiff,
|
||||
rawloader,
|
||||
camera,
|
||||
makernote,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Decoder for ErfDecoder<'a> {
|
||||
fn raw_image(&self, file: &RawSource, _params: &RawDecodeParams, dummy: bool) -> Result<RawImage> {
|
||||
let raw = self
|
||||
.tiff
|
||||
.find_first_ifd_with_tag(TiffCommonTag::CFAPattern)
|
||||
.ok_or_else(|| RawlerError::DecoderFailed(format!("Failed to find a IFD with CFAPattern tag")))?;
|
||||
let width = fetch_tiff_tag!(raw, TiffCommonTag::ImageWidth).force_usize(0);
|
||||
let height = fetch_tiff_tag!(raw, TiffCommonTag::ImageLength).force_usize(0);
|
||||
let offset = fetch_tiff_tag!(raw, TiffCommonTag::StripOffsets).force_usize(0);
|
||||
let src = file.subview_until_eof(offset as u64)?;
|
||||
|
||||
let image = decode_12be_wcontrol(src, width, height, dummy);
|
||||
let cpp = 1;
|
||||
|
||||
let blacklevel = self.get_blacklevel(cpp);
|
||||
let photometric = RawPhotometricInterpretation::Cfa(CFAConfig::new_from_camera(&self.camera));
|
||||
let img = RawImage::new(self.camera.clone(), image, cpp, self.get_wb()?, photometric, blacklevel, None, dummy);
|
||||
Ok(img)
|
||||
}
|
||||
|
||||
fn format_dump(&self) -> FormatDump {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn raw_metadata(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result<RawMetadata> {
|
||||
let exif = Exif::new(self.tiff.root_ifd())?;
|
||||
let mdata = RawMetadata::new(&self.camera, exif);
|
||||
Ok(mdata)
|
||||
}
|
||||
|
||||
fn format_hint(&self) -> FormatHint {
|
||||
FormatHint::ERF
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ErfDecoder<'a> {
|
||||
fn get_wb(&self) -> Result<[f32; 4]> {
|
||||
let levels = fetch_tiff_tag!(self.makernote, TiffCommonTag::EpsonWB);
|
||||
if levels.count() != 256 {
|
||||
Err(RawlerError::DecoderFailed("ERF: Levels count is off".to_string()))
|
||||
} else {
|
||||
let r = BEu16(levels.get_data(), 48) as f32;
|
||||
let b = BEu16(levels.get_data(), 50) as f32;
|
||||
Ok([r * 508.0 * 1.078 / 65536.0, 1.0, b * 382.0 * 1.173 / 65536.0, f32::NAN])
|
||||
}
|
||||
}
|
||||
|
||||
fn get_blacklevel(&self, cpp: usize) -> Option<BlackLevel> {
|
||||
if let Some(levels) = self.makernote.get_entry(0x0401) {
|
||||
let levels = [levels.force_u16(0), levels.force_u16(1), levels.force_u16(2), levels.force_u16(3)];
|
||||
return Some(BlackLevel::new(&levels, self.camera.cfa.width, self.camera.cfa.height, cpp));
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user