mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-19 02:10:25 -05:00
Merge PR #1475 (rebased)
# Conflicts: # crates/raw/examples/rawinfo.rs # crates/raw/src/lib.rs # crates/raw/src/vendor/arw.rs # crates/raw/src/vendor/erf.rs # crates/raw/src/vendor/mef.rs # crates/raw/src/vendor/nef.rs # crates/raw/tests/lossy_dng.rs # crates/raw/tests/robust.rs
This commit is contained in:
commit
51a784cd95
29 files changed
+102
-12
No files matched your search
@@ -1937,6 +1937,7 @@ mod tests {
|
||||
color: ColorData::default(),
|
||||
wb_multipliers: Some([1.0; 3]),
|
||||
linearized: true,
|
||||
pixel_aspect: 1.0,
|
||||
opcodes: OpcodeLists::default(),
|
||||
metadata: lightcraft_meta::Metadata::default(),
|
||||
lens_metadata: Default::default(),
|
||||
@@ -2326,6 +2327,7 @@ mod tests {
|
||||
color,
|
||||
wb_multipliers: Some([2.0, 1.0, 1.5]),
|
||||
linearized: false,
|
||||
pixel_aspect: 1.0,
|
||||
opcodes: Default::default(),
|
||||
metadata: lightcraft_raw::Metadata { make: Some(make.to_owned()), model: Some(model.to_owned()), ..Default::default() },
|
||||
lens_metadata: Default::default(),
|
||||
@@ -3540,6 +3542,7 @@ mod tests {
|
||||
color: ColorData::default(),
|
||||
wb_multipliers: Some([1.0; 3]),
|
||||
linearized: true,
|
||||
pixel_aspect: 1.0,
|
||||
opcodes: OpcodeLists::default(),
|
||||
metadata: lightcraft_meta::Metadata { make: Some("SONY".into()), model: Some("ILCE-7M4".into()), ..Default::default() },
|
||||
lens_metadata: Default::default(),
|
||||
|
||||
@@ -159,10 +159,8 @@ pub fn probe_bytes(name: &str, bytes: &[u8]) -> Result<ProbeInfo, String> {
|
||||
}
|
||||
Err(Err(e)) => return Err(e),
|
||||
};
|
||||
let (mut w, mut h) = (raw.crop.width.max(1) as u32, raw.crop.height.max(1) as u32);
|
||||
if w <= 1 || h <= 1 {
|
||||
(w, h) = (raw.active_area.width as u32, raw.active_area.height as u32);
|
||||
}
|
||||
let (w, h) = raw.developed_size();
|
||||
let (mut w, mut h) = (w.max(1) as u32, h.max(1) as u32);
|
||||
if raw.orientation.swaps_axes() {
|
||||
std::mem::swap(&mut w, &mut h);
|
||||
}
|
||||
|
||||
@@ -64,8 +64,7 @@ fn frame_crop_factor(camera: Option<f64>, focal: f64, focal_35mm: Option<f64>) -
|
||||
pub fn for_raw(raw: &lightcraft_raw::RawInfo, meta: impl FnOnce() -> lightcraft_meta::Metadata) -> Option<EmbeddedLens> {
|
||||
crate::files::embedded_lens(raw).or_else(|| {
|
||||
let db = database()?;
|
||||
let c = raw.crop.clipped(raw.active_area.width, raw.active_area.height);
|
||||
let (w, h) = if c.width == 0 || c.height == 0 { (raw.active_area.width, raw.active_area.height) } else { (c.width, c.height) };
|
||||
let (w, h) = raw.developed_size();
|
||||
lookup(db, &meta(), w as f64, h as f64, raw.orientation)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -584,6 +584,7 @@ pub(crate) fn synthetic_dng_of(w: usize, h: usize, cfa: &str, data: Vec<u16>, xm
|
||||
},
|
||||
wb_multipliers: None,
|
||||
linearized: false,
|
||||
pixel_aspect: 1.0,
|
||||
opcodes: OpcodeLists::default(),
|
||||
metadata,
|
||||
lens_metadata: Default::default(),
|
||||
|
||||
@@ -309,6 +309,7 @@ mod tests {
|
||||
linearized: false,
|
||||
opcodes: OpcodeLists::default(),
|
||||
lens_metadata: Default::default(),
|
||||
pixel_aspect: 1.0,
|
||||
metadata: Metadata::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,6 +112,7 @@ pub fn write_linear_dng(
|
||||
color: cd,
|
||||
wb_multipliers: None,
|
||||
linearized: false,
|
||||
pixel_aspect: 1.0,
|
||||
opcodes: OpcodeLists { list3: lens.to_vec(), ..Default::default() },
|
||||
metadata: meta,
|
||||
lens_metadata: Default::default(),
|
||||
|
||||
@@ -228,6 +228,7 @@ mod tests {
|
||||
opcodes: OpcodeLists::default(),
|
||||
metadata: Default::default(),
|
||||
lens_metadata: Default::default(),
|
||||
pixel_aspect: 1.0,
|
||||
};
|
||||
let path = dir.path("valid.dng");
|
||||
std::fs::write(&path, write_dng(&raw, &DngWriteOptions::default()).expect("encode generated fixture")).expect("write fixture");
|
||||
|
||||
@@ -24,7 +24,7 @@ impl RawImage {
|
||||
/// and B; Bayer: `k` even, so that every block has the same layout)?
|
||||
pub fn can_bin(&self, k: usize) -> bool {
|
||||
let Some(cfa) = &self.cfa else { return false };
|
||||
if k < 2 || self.cpp != 1 || !cfa.valid() || (cfa.is_bayer() && !k.is_multiple_of(2)) {
|
||||
if k < 2 || self.cpp != 1 || (self.pixel_aspect - 1.0).abs() >= 0.01 || !cfa.valid() || (cfa.is_bayer() && !k.is_multiple_of(2)) {
|
||||
return false;
|
||||
}
|
||||
// every window position relative to the pattern
|
||||
@@ -163,6 +163,7 @@ mod tests {
|
||||
color: ColorData::default(),
|
||||
wb_multipliers: None,
|
||||
linearized: false,
|
||||
pixel_aspect: 1.0,
|
||||
opcodes: OpcodeLists::default(),
|
||||
metadata: Metadata::default(),
|
||||
lens_metadata: Default::default(),
|
||||
|
||||
@@ -287,6 +287,7 @@ mod tests {
|
||||
color,
|
||||
wb_multipliers: None,
|
||||
linearized: false,
|
||||
pixel_aspect: 1.0,
|
||||
opcodes: Default::default(),
|
||||
metadata: Default::default(),
|
||||
lens_metadata: Default::default(),
|
||||
|
||||
@@ -338,6 +338,7 @@ pub(crate) fn decode_as(bytes: &[u8], mode: Mode, format: RawFormat) -> Result<R
|
||||
color: color_data(ifd0, raw, tiff.order),
|
||||
wb_multipliers: None,
|
||||
linearized,
|
||||
pixel_aspect: default_scale_aspect(raw.f64s(t::DEFAULT_SCALE).as_deref()),
|
||||
opcodes,
|
||||
metadata,
|
||||
lens_metadata: Default::default(),
|
||||
@@ -346,8 +347,25 @@ pub(crate) fn decode_as(bytes: &[u8], mode: Mode, format: RawFormat) -> Result<R
|
||||
Ok(img)
|
||||
}
|
||||
|
||||
/// Pixel height over width from `DefaultScale` (horizontal, vertical): only a clear 1.5 to 4 ratio counts (the rows stretch; a wider-than-tall pixel is left alone).
|
||||
fn default_scale_aspect(scale: Option<&[f64]>) -> f32 {
|
||||
match scale {
|
||||
Some([h, v]) if *h > 0.0 && *v > 0.0 && (1.5..=4.0).contains(&(v / h)) => (v / h) as f32,
|
||||
_ => 1.0,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn default_scale_makes_tall_pixels() {
|
||||
assert_eq!(default_scale_aspect(Some(&[1.0, 2.0])), 2.0);
|
||||
assert_eq!(default_scale_aspect(Some(&[1.0, 1.0])), 1.0);
|
||||
assert_eq!(default_scale_aspect(Some(&[2.0, 1.0])), 1.0);
|
||||
assert_eq!(default_scale_aspect(Some(&[1.0, 1.2])), 1.0);
|
||||
assert_eq!(default_scale_aspect(None), 1.0);
|
||||
}
|
||||
|
||||
use super::*;
|
||||
|
||||
/// Store `image` the way DNG 1.7 interleaves it: row `r` of the image is written to stored row
|
||||
|
||||
@@ -538,6 +538,7 @@ pub fn write_rendered_dng(
|
||||
color,
|
||||
wb_multipliers: None,
|
||||
linearized: false,
|
||||
pixel_aspect: 1.0,
|
||||
opcodes: crate::OpcodeLists::default(),
|
||||
metadata: metadata.clone(),
|
||||
lens_metadata: Default::default(),
|
||||
|
||||
+40
-4
@@ -435,13 +435,27 @@ pub struct RawInfo {
|
||||
/// Lens-correction tables the file records, decoded but not necessarily applied (see [`crate::lens_metadata`]).
|
||||
#[serde(default)]
|
||||
pub lens_metadata: LensMetadata,
|
||||
/// See [`RawImage::pixel_aspect`].
|
||||
#[serde(default = "square_pixels")]
|
||||
pub pixel_aspect: f32,
|
||||
}
|
||||
|
||||
fn square_pixels() -> f32 {
|
||||
1.0
|
||||
}
|
||||
|
||||
/// Rows of a picture `height` rows tall once its pixels (taller than wide by `aspect`) are made square.
|
||||
pub fn stretched_height(height: usize, aspect: f32) -> usize {
|
||||
if (aspect - 1.0).abs() < 0.01 { height } else { ((height as f32 * aspect).round() as usize).max(1) }
|
||||
}
|
||||
|
||||
impl RawInfo {
|
||||
/// Size of the developed image before orientation: the default crop, else the active area.
|
||||
/// Size of the developed image before orientation: the default crop, else the active area, with the rows
|
||||
/// stretched for non-square pixels.
|
||||
pub fn developed_size(&self) -> (usize, usize) {
|
||||
let c = self.crop.clipped(self.active_area.width, self.active_area.height);
|
||||
if c.width > 1 && c.height > 1 { (c.width, c.height) } else { (self.active_area.width, self.active_area.height) }
|
||||
let (w, h) = if c.width > 1 && c.height > 1 { (c.width, c.height) } else { (self.active_area.width, self.active_area.height) };
|
||||
(w, stretched_height(h, self.pixel_aspect))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -666,6 +680,10 @@ pub struct RawImage {
|
||||
pub wb_multipliers: Option<[f32; 3]>,
|
||||
/// Whether a `LinearizationTable` was applied to `data`.
|
||||
pub linearized: bool,
|
||||
/// Height of a sensor pixel over its width (1.0 for square pixels). The D1X and D1H write 2.0: their frame is
|
||||
/// 4028 x 1324 and the picture is 3:2 only once the rows are doubled. [`Self::develop`] stretches the rows by
|
||||
/// this factor.
|
||||
pub pixel_aspect: f32,
|
||||
pub opcodes: OpcodeLists,
|
||||
pub metadata: Metadata,
|
||||
/// Lens-correction tables the file records, decoded but not necessarily applied (see [`crate::lens_metadata`]); only
|
||||
@@ -704,6 +722,7 @@ impl RawImage {
|
||||
opcodes: self.opcodes.clone(),
|
||||
metadata: self.metadata.clone(),
|
||||
lens_metadata: self.lens_metadata.clone(),
|
||||
pixel_aspect: self.pixel_aspect,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -724,6 +743,7 @@ impl RawImage {
|
||||
opcodes: self.opcodes,
|
||||
metadata: self.metadata,
|
||||
lens_metadata: self.lens_metadata,
|
||||
pixel_aspect: self.pixel_aspect,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -827,10 +847,13 @@ impl RawImage {
|
||||
pub fn finish_demosaiced(&self, mut rgb: Rgb32f) -> Rgb32f {
|
||||
opcodes::apply_list3(&self.opcodes.list3, &mut rgb);
|
||||
let c = self.develop_crop(rgb.width, rgb.height);
|
||||
if c.x == 0 && c.y == 0 && c.width == rgb.width && c.height == rgb.height {
|
||||
let rgb =
|
||||
if c.x == 0 && c.y == 0 && c.width == rgb.width && c.height == rgb.height { rgb } else { rgb.into_crop(c.x, c.y, c.width, c.height) };
|
||||
let h = stretched_height(rgb.height, self.pixel_aspect);
|
||||
if h == rgb.height {
|
||||
return rgb;
|
||||
}
|
||||
rgb.into_crop(c.x, c.y, c.width, c.height)
|
||||
lightcraft_raster::resample::resize(&rgb, rgb.width, h, lightcraft_raster::resample::Filter::Mitchell)
|
||||
}
|
||||
|
||||
/// The part of a `width × height` demosaiced picture (the active area) that [`Self::develop`] keeps: the default
|
||||
@@ -889,6 +912,7 @@ mod tests {
|
||||
color: ColorData::default(),
|
||||
wb_multipliers: None,
|
||||
linearized: false,
|
||||
pixel_aspect: 1.0,
|
||||
opcodes: OpcodeLists::default(),
|
||||
metadata: Metadata::default(),
|
||||
lens_metadata: Default::default(),
|
||||
@@ -906,6 +930,17 @@ mod tests {
|
||||
// a crop that pokes out is clipped to the picture
|
||||
whole.crop = Rect::new(6, 4, 10, 10);
|
||||
assert_eq!(whole.develop_crop(8, 6), Rect::new(6, 4, 2, 2));
|
||||
|
||||
// tall pixels (D1X: 2.0) are stretched to square ones: the rows double, `developed_size` says so
|
||||
let mut tall = raw.clone();
|
||||
tall.pixel_aspect = 2.0;
|
||||
let d = tall.develop(Method::Bilinear).unwrap();
|
||||
assert_eq!((d.width, d.height), (5, 8));
|
||||
assert_eq!(tall.info().developed_size(), (5, 8));
|
||||
assert_eq!(raw.info().developed_size(), (5, 4));
|
||||
assert!(!tall.can_bin(2));
|
||||
assert_eq!(stretched_height(1324, 2.0), 2648);
|
||||
assert_eq!(stretched_height(1324, 1.0), 1324);
|
||||
}
|
||||
|
||||
/// A maker-note crop (`PEF` AOC / `ORF` ImageProcessing) with an origin of `u64::MAX` used to
|
||||
@@ -933,6 +968,7 @@ mod tests {
|
||||
opcodes: OpcodeLists::default(),
|
||||
metadata: Metadata::default(),
|
||||
lens_metadata: Default::default(),
|
||||
pixel_aspect: 1.0,
|
||||
};
|
||||
assert!(raw.validate().is_err(), "`x + width` wrapped: the area is outside the image");
|
||||
assert!(raw.normalized().is_err());
|
||||
|
||||
@@ -135,6 +135,7 @@ mod tests {
|
||||
color: ColorData::default(),
|
||||
wb_multipliers: None,
|
||||
linearized: false,
|
||||
pixel_aspect: 1.0,
|
||||
opcodes: OpcodeLists::default(),
|
||||
metadata: Metadata::default(),
|
||||
lens_metadata: Default::default(),
|
||||
|
||||
Vendored
+1
@@ -810,6 +810,7 @@ pub(crate) fn decode(bytes: &[u8], mode: Mode) -> Result<RawImage> {
|
||||
// makes a neutral surface magenta. WB edits remain relative to this as-shot RGB.
|
||||
wb_multipliers: if linear_rgb { Some([1.0; 3]) } else { wb },
|
||||
linearized: false,
|
||||
pixel_aspect: 1.0,
|
||||
// only validated components become opcodes (see `arw_lens`, and `arw_lens_rm6` for the ILCE-7RM6)
|
||||
opcodes: OpcodeLists { list3: warp.into_iter().chain(rm6).collect(), ..Default::default() },
|
||||
metadata,
|
||||
|
||||
Vendored
+1
@@ -249,6 +249,7 @@ pub(crate) fn decode(bytes: &[u8], mode: Mode) -> Result<RawImage> {
|
||||
color: ColorData::default(),
|
||||
wb_multipliers: wb,
|
||||
linearized: false,
|
||||
pixel_aspect: 1.0,
|
||||
opcodes: OpcodeLists::default(),
|
||||
metadata,
|
||||
lens_metadata: Default::default(),
|
||||
|
||||
Vendored
+1
@@ -391,6 +391,7 @@ pub(super) fn decode(bytes: &[u8], tiff: &Tiff, raw: &Ifd, mode: Mode) -> Result
|
||||
// the camera's white balance is already applied, as in Sony's linear YCbCr
|
||||
wb_multipliers: Some([1.0; 3]),
|
||||
linearized: false,
|
||||
pixel_aspect: 1.0,
|
||||
opcodes: OpcodeLists::default(),
|
||||
metadata,
|
||||
lens_metadata: Default::default(),
|
||||
|
||||
Vendored
+1
@@ -253,6 +253,7 @@ pub(crate) fn decode(bytes: &[u8], mode: Mode) -> Result<RawImage> {
|
||||
color: ColorData::default(),
|
||||
wb_multipliers: levels.wb,
|
||||
linearized: false,
|
||||
pixel_aspect: 1.0,
|
||||
opcodes: OpcodeLists::default(),
|
||||
metadata,
|
||||
lens_metadata: Default::default(),
|
||||
|
||||
Vendored
+1
@@ -124,6 +124,7 @@ pub(crate) fn decode(bytes: &[u8], mode: Mode) -> Result<RawImage> {
|
||||
opcodes: OpcodeLists::default(),
|
||||
metadata,
|
||||
lens_metadata: Default::default(),
|
||||
pixel_aspect: 1.0,
|
||||
};
|
||||
img.validate_for(mode)?;
|
||||
Ok(img)
|
||||
|
||||
Vendored
+1
@@ -115,6 +115,7 @@ pub(crate) fn decode(bytes: &[u8], mode: Mode) -> Result<RawImage> {
|
||||
color: ColorData::default(),
|
||||
wb_multipliers: wb,
|
||||
linearized: false,
|
||||
pixel_aspect: 1.0,
|
||||
opcodes: OpcodeLists::default(),
|
||||
metadata,
|
||||
lens_metadata: Default::default(),
|
||||
|
||||
Vendored
+1
@@ -122,6 +122,7 @@ pub(crate) fn decode(bytes: &[u8], mode: Mode) -> Result<RawImage> {
|
||||
opcodes: OpcodeLists::default(),
|
||||
metadata,
|
||||
lens_metadata: Default::default(),
|
||||
pixel_aspect: 1.0,
|
||||
};
|
||||
img.validate_for(mode)?;
|
||||
Ok(img)
|
||||
|
||||
Vendored
+13
-1
@@ -175,6 +175,16 @@ fn measured_body(model: &str, w: usize, h: usize, bits: u32) -> Option<&'static
|
||||
MEASURED_BODIES.iter().find(|b| b.model == model.trim() && b.size == (w, h) && b.bits == bits)
|
||||
}
|
||||
|
||||
/// Pixel height over width from the raw IFD's resolution tags: the D1X and D1H write 600 x 300 per inch for a
|
||||
/// 4028 x 1324 frame, rows twice as tall as the columns are wide. Only ratios from 1.5 to 4 count (a frame
|
||||
/// squashed 3:1 or 2:1), the rest is rounding or a stray tag.
|
||||
pub(crate) fn pixel_aspect_of(raw: &Ifd) -> f32 {
|
||||
match (raw.f64(t::X_RESOLUTION), raw.f64(t::Y_RESOLUTION)) {
|
||||
(Some(x), Some(y)) if x > 0.0 && y > 0.0 && (1.5..=4.0).contains(&(x / y)) => (x / y).round() as f32,
|
||||
_ => 1.0,
|
||||
}
|
||||
}
|
||||
|
||||
fn raw_ifd(tiff: &Tiff) -> Option<&Ifd> {
|
||||
tiff.all_ifds()
|
||||
.into_iter()
|
||||
@@ -268,9 +278,10 @@ pub(crate) fn decode(bytes: &[u8], mode: Mode) -> Result<RawImage> {
|
||||
Some(&MeasuredBody { crop: (x, y, cw, ch), .. }) if x + cw <= active_w && y + ch <= h => Rect::new(x, y, cw, ch),
|
||||
_ => default_crop(mn.as_ref(), active_w, h),
|
||||
};
|
||||
let pixel_aspect = pixel_aspect_of(raw);
|
||||
let mut metadata = lightcraft_meta::from_tiff(&tiff);
|
||||
metadata.width = Some(crop.width as u32);
|
||||
metadata.height = Some(crop.height as u32);
|
||||
metadata.height = Some(crate::stretched_height(crop.height, pixel_aspect) as u32);
|
||||
let img = RawImage {
|
||||
format: RawFormat::Nef,
|
||||
width: w,
|
||||
@@ -290,6 +301,7 @@ pub(crate) fn decode(bytes: &[u8], mode: Mode) -> Result<RawImage> {
|
||||
color: ColorData::default(),
|
||||
wb_multipliers: wb,
|
||||
linearized: false,
|
||||
pixel_aspect,
|
||||
// Nikon's in-file distortion correction, about the optical centre (which follows the sensor shift)
|
||||
opcodes: OpcodeLists {
|
||||
list3: super::nef_lens::distortion(&model, raw, Rect::new(0, 0, active_w, h), crop).into_iter().collect(),
|
||||
|
||||
Vendored
+1
@@ -334,6 +334,7 @@ pub(crate) fn decode(bytes: &[u8], mode: Mode) -> Result<RawImage> {
|
||||
color: ColorData::default(),
|
||||
wb_multipliers: wb,
|
||||
linearized: false,
|
||||
pixel_aspect: 1.0,
|
||||
opcodes: OpcodeLists::default(),
|
||||
metadata,
|
||||
lens_metadata: Default::default(),
|
||||
|
||||
Vendored
+1
@@ -335,6 +335,7 @@ pub(crate) fn decode(bytes: &[u8], mode: Mode) -> Result<RawImage> {
|
||||
color: ColorData::default(),
|
||||
wb_multipliers: wb,
|
||||
linearized: false,
|
||||
pixel_aspect: 1.0,
|
||||
opcodes: OpcodeLists::default(),
|
||||
metadata,
|
||||
lens_metadata: Default::default(),
|
||||
|
||||
Vendored
+1
@@ -212,6 +212,7 @@ pub(crate) fn decode(bytes: &[u8], mode: Mode) -> Result<RawImage> {
|
||||
color: ColorData::default(),
|
||||
wb_multipliers: wb,
|
||||
linearized: false,
|
||||
pixel_aspect: 1.0,
|
||||
opcodes: OpcodeLists { list3: super::raf_lens::corrections(&camera_name(bytes), &ifd, active), ..Default::default() },
|
||||
metadata,
|
||||
lens_metadata: Default::default(),
|
||||
|
||||
Vendored
+1
@@ -614,6 +614,7 @@ pub(crate) fn decode(bytes: &[u8], mode: Mode) -> Result<RawImage> {
|
||||
color: ColorData::default(),
|
||||
wb_multipliers: wb,
|
||||
linearized: false,
|
||||
pixel_aspect: 1.0,
|
||||
opcodes: OpcodeLists { list3: distortion(ifd0, active).into_iter().collect(), ..Default::default() },
|
||||
metadata,
|
||||
lens_metadata: Default::default(),
|
||||
|
||||
Vendored
+1
@@ -184,6 +184,7 @@ pub(crate) fn decode(bytes: &[u8], mode: Mode) -> Result<RawImage> {
|
||||
color: ColorData::default(),
|
||||
wb_multipliers: wb,
|
||||
linearized: false,
|
||||
pixel_aspect: 1.0,
|
||||
opcodes: OpcodeLists::default(),
|
||||
metadata,
|
||||
lens_metadata: Default::default(),
|
||||
|
||||
@@ -59,6 +59,7 @@ fn synthetic(w: usize, h: usize, cfa: Option<Cfa>, cpp: usize) -> RawImage {
|
||||
color,
|
||||
wb_multipliers: None,
|
||||
linearized: false,
|
||||
pixel_aspect: 1.0,
|
||||
opcodes: OpcodeLists::default(),
|
||||
metadata,
|
||||
lens_metadata: Default::default(),
|
||||
|
||||
@@ -38,6 +38,7 @@ fn mosaic(w: usize, h: usize) -> RawImage {
|
||||
opcodes: OpcodeLists::default(),
|
||||
metadata: Default::default(),
|
||||
lens_metadata: Default::default(),
|
||||
pixel_aspect: 1.0,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ fn sample(comp: DngCompression) -> Vec<u8> {
|
||||
color: ColorData::default(),
|
||||
wb_multipliers: None,
|
||||
linearized: false,
|
||||
pixel_aspect: 1.0,
|
||||
opcodes: OpcodeLists::default(),
|
||||
metadata: Default::default(),
|
||||
lens_metadata: Default::default(),
|
||||
@@ -165,6 +166,7 @@ fn non_finite_black_levels_and_samples_develop() {
|
||||
opcodes: OpcodeLists::default(),
|
||||
metadata: Default::default(),
|
||||
lens_metadata: Default::default(),
|
||||
pixel_aspect: 1.0,
|
||||
};
|
||||
for img in [raw.clone(), lightcraft_raw::decode(&lightcraft_raw::write_dng(&raw, &DngWriteOptions::default()).unwrap()).unwrap()] {
|
||||
let rgb = img.develop(Method::Ahd).unwrap();
|
||||
|
||||
Reference in new issue
Block a user