mirror of
https://github.com/storytold/photocraft.git
synced 2026-10-18 12:05:19 +02:00
Co-authored-by: optimalbytee <optimalbytee@users.noreply.github.com> Co-authored-by: Brandon Thomas <echelon@gmail.com>
92 lines
3.5 KiB
Rust
92 lines
3.5 KiB
Rust
//! Development limits and hostile public sensor metadata.
|
|
use photocraft_raw::testgen::DngSpec;
|
|
use photocraft_raw::*;
|
|
|
|
fn small_sensor() -> Sensor {
|
|
decode(&DngSpec::cfa(64, 48, vec![1000; 64 * 48]).build(), &Limits::default()).unwrap()
|
|
}
|
|
|
|
#[test]
|
|
fn checks_peak_live_buffers_instead_of_summing_disjoint_phases() {
|
|
let sensor = decode(&DngSpec::cfa(128, 96, vec![1000; 128 * 96]).build(), &Limits::default()).unwrap();
|
|
let mut opts = DevelopOptions { demosaic: Demosaic::Mhc, ..Default::default() };
|
|
opts.limits.max_alloc = 128 * 96 * 18 + (4096 + 2) * 4;
|
|
let expected = develop_sensor(&sensor, &DevelopOptions { demosaic: Demosaic::Mhc, ..Default::default() }).unwrap();
|
|
assert_eq!(develop_sensor(&sensor, &opts).unwrap().rgb, expected.rgb);
|
|
opts.limits.max_alloc -= 1;
|
|
assert!(matches!(develop_sensor(&sensor, &opts), Err(RawError::LimitExceeded(_))));
|
|
}
|
|
|
|
#[test]
|
|
fn monochrome_and_rgb_linear_raw_preserve_output_and_memory_limits() {
|
|
let (w, h) = (32, 24);
|
|
for samples in [1, 3] {
|
|
let data = (0..w * h).flat_map(|i| (0..samples).map(move |c| (i % w * 1000 + c * 5000) as u16)).collect();
|
|
let spec = DngSpec { samples, monochrome: samples == 1, ..DngSpec::cfa(w, h, data) };
|
|
let sensor = decode(&spec.build(), &Limits::default()).unwrap();
|
|
assert!(sensor.cfa.is_none());
|
|
assert_eq!(sensor.samples, samples);
|
|
let expected = develop_sensor(&sensor, &DevelopOptions::default()).unwrap();
|
|
let mut opts = DevelopOptions::default();
|
|
opts.limits.max_alloc = 32 * 1024;
|
|
let got = develop_sensor(&sensor, &opts).unwrap();
|
|
assert_eq!(got.rgb, expected.rgb);
|
|
assert_eq!((got.width, got.height), (w as u32, h as u32));
|
|
if samples == 1 {
|
|
assert!(got.rgb.as_chunks::<3>().0.iter().all(|p| p[0] == p[1] && p[1] == p[2]));
|
|
}
|
|
// Even the encoded RGB output alone cannot fit this budget.
|
|
opts.limits.max_alloc = (expected.rgb.len() * 2 - 1) as u64;
|
|
assert!(matches!(develop_sensor(&sensor, &opts), Err(RawError::LimitExceeded(_))));
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn invalid_public_sensor_metadata_returns_errors() {
|
|
let sensor = small_sensor();
|
|
let mut cases = Vec::new();
|
|
let mut s = sensor.clone();
|
|
s.crop.x = usize::MAX;
|
|
cases.push(s);
|
|
let mut s = sensor.clone();
|
|
s.width = usize::MAX;
|
|
cases.push(s);
|
|
let mut s = sensor.clone();
|
|
s.samples = usize::MAX;
|
|
cases.push(s);
|
|
let mut s = sensor.clone();
|
|
s.cfa.as_mut().unwrap().width = 0;
|
|
cases.push(s);
|
|
let mut s = sensor.clone();
|
|
s.cfa.as_mut().unwrap().colors.clear();
|
|
cases.push(s);
|
|
let mut s = sensor.clone();
|
|
s.cfa.as_mut().unwrap().colors[0] = 255;
|
|
cases.push(s);
|
|
let mut s = sensor.clone();
|
|
s.cfa = None;
|
|
s.samples = 2;
|
|
s.data.resize(64 * 48 * 2, 1000);
|
|
cases.push(s);
|
|
let mut s = sensor.clone();
|
|
s.samples = 3;
|
|
s.data.resize(64 * 48 * 3, 1000);
|
|
cases.push(s);
|
|
for s in cases {
|
|
assert!(develop_sensor(&s, &DevelopOptions::default()).is_err());
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn extreme_cfa_and_black_origins_do_not_overflow() {
|
|
let mut sensor = small_sensor();
|
|
let cfa = sensor.cfa.as_mut().unwrap();
|
|
cfa.origin_x = usize::MAX;
|
|
cfa.origin_y = usize::MAX;
|
|
assert!(cfa.is_bayer());
|
|
sensor.black.rows = usize::MAX;
|
|
sensor.black.cols = usize::MAX;
|
|
assert!(develop_sensor(&sensor, &DevelopOptions::default()).is_ok());
|
|
assert_eq!(Cfa { width: 0, height: 0, colors: vec![], origin_x: 0, origin_y: 0 }.color(1, 2), 1);
|
|
}
|