image_hdr/
exif.rs

1//! Helpers to extract necessary EXIF information from source images
2
3use crate::Error;
4use exif::{Exif, In, Tag, Value};
5
6/// Extract the exif information from the bytes of an image file
7///
8/// # Errors
9/// - failed to extract exif data
10pub fn get_exif_data(data: &[u8]) -> Result<Exif, Error> {
11    let mut buf_reader = std::io::Cursor::new(data);
12    let exif_reader = exif::Reader::new();
13    let exif = exif_reader.read_from_container(&mut buf_reader)?;
14
15    Ok(exif)
16}
17
18/// Extract the exposure time in seconds from exif information
19///
20/// # Errors
21/// - failed to exposure from exif data
22pub fn get_exposures(exif: &Exif) -> Result<f32, Error> {
23    match exif
24        .get_field(Tag::ExposureTime, In::PRIMARY)
25        .ok_or(Error::ExifError(exif::Error::NotFound(
26            "ExposureTime not found",
27        )))?
28        .value
29    {
30        Value::Rational(ref v) if !v.is_empty() => Ok(v[0].to_f32()),
31        _ => Ok(0.),
32    }
33}
34
35/// Extract the gains from exif information
36///
37/// # Errors
38/// - failed to gains from exif data
39#[allow(clippy::cast_precision_loss)]
40pub fn get_gains(exif: &Exif) -> Result<f32, Error> {
41    match exif
42        .get_field(Tag::ISOSpeed, In::PRIMARY)
43        .unwrap_or(
44            exif.get_field(Tag::StandardOutputSensitivity, In::PRIMARY)
45                .unwrap_or(
46                    exif.get_field(Tag::PhotographicSensitivity, In::PRIMARY)
47                        .ok_or(Error::ExifError(exif::Error::NotFound("ISO not found")))?,
48                ),
49        )
50        .value
51    {
52        Value::Long(ref v) if !v.is_empty() => Ok(v[0] as f32),
53        Value::Short(ref v) if !v.is_empty() => Ok(f32::from(v[0])),
54        _ => Ok(0.),
55    }
56}