Krolyxon
Commit 1d9227a

Branches

Tags

Refs →

remagesrcdecoderaw.rs

69 lines · 2.5 KB · Rust

1//! Camera RAW through `rawler`: the embedded preview first (fast), a full develop on demand
2//! once the view zooms past the preview's resolution.
3
4use std::path::Path;
5
6use anyhow::anyhow;
7use image::metadata::Orientation;
8use rawler::decoders::RawDecodeParams;
9use rawler::imgop::develop::RawDevelop;
10use rawler::rawsource::RawSource;
11
12use super::color;
13use super::{DecodedImage, Options, Refine};
14
15fn orientation(o: rawler::decoders::Orientation, opts: &Options) -> Orientation {
16 if !opts.auto_orient {
17 return Orientation::NoTransforms;
18 }
19 Orientation::from_exif(o.to_u16() as u8).unwrap_or(Orientation::NoTransforms)
20}
21
22pub fn decode(path: &Path, opts: &Options) -> anyhow::Result<DecodedImage> {
23 let src = RawSource::new(path)?;
24 let decoder = rawler::get_decoder(&src)?;
25 let params = RawDecodeParams::default();
26 let preview = decoder
27 .preview_image(&src, &params)
28 .ok()
29 .flatten()
30 .or_else(|| decoder.full_image(&src, &params).ok().flatten());
31 let Some(preview) = preview else {
32 return develop(path, opts);
33 };
34 // The raw data's size (cheap: no pixels decoded) is the size the view works in.
35 let raw = decoder.raw_image(&src, &params, true)?;
36 let o = orientation(raw.orientation, opts);
37 let (size, pixels) = color::to_rgba8(preview);
38 let (size, pixels) = color::orient(size, pixels, o);
39 let (rw, rh) = match raw.crop_area {
40 Some(r) => (r.d.w, r.d.h),
41 None => (raw.width, raw.height),
42 };
43 let raw_long = rw.max(rh) as u32;
44 let long = size[0].max(size[1]);
45 let mut img = DecodedImage::still(size, pixels, "RAW");
46 if raw_long > long {
47 // Same shape as the preview, scaled up to the sensor's resolution.
48 let k = raw_long as f64 / long as f64;
49 img.source_size = [
50 (size[0] as f64 * k).round() as u32,
51 (size[1] as f64 * k).round() as u32,
52 ];
53 img.refine = Some(Refine::Raw);
54 }
55 Ok(img)
56}
57
58/// Demosaic and develop the raw data in full.
59pub fn develop(path: &Path, opts: &Options) -> anyhow::Result<DecodedImage> {
60 let raw = rawler::decode_file(path)?;
61 let o = orientation(raw.orientation, opts);
62 let dynamic = RawDevelop::default()
63 .develop_intermediate(&raw)?
64 .to_dynamic_image()
65 .ok_or_else(|| anyhow!("develop produced no image"))?;
66 let (size, pixels) = color::to_rgba8(dynamic);
67 let (size, pixels) = color::orient(size, pixels, o);
68 Ok(DecodedImage::still(size, pixels, "RAW"))
69}