use crate::{PanoAngles, Projection};
pub struct PanoExif {
pub projection_type: Option<String>,
pub pose_heading_degrees: Option<f64>,
pub full_pano_width_pixels: u32,
pub full_pano_height_pixels: u32,
pub cropped_area_top_pixels: u32,
pub cropped_area_image_width_pixels: u32,
pub cropped_area_image_height_pixels: u32,
}
#[must_use]
pub fn exif_to_partial_pano_config(exif_info: &PanoExif) -> PanoAngles {
let cropped_area_img_width_pixels = f64::from(exif_info.cropped_area_image_width_pixels);
let cropped_area_image_height_pixels = f64::from(exif_info.cropped_area_image_height_pixels);
let full_pano_width_pixels = f64::from(exif_info.full_pano_width_pixels);
let full_pano_height_pixels = f64::from(exif_info.full_pano_height_pixels);
let cropped_area_top_pixels = f64::from(exif_info.cropped_area_top_pixels);
let haov = (cropped_area_img_width_pixels / full_pano_width_pixels) * 360.0;
let vaov = (cropped_area_image_height_pixels / full_pano_height_pixels) * 180.0;
let crop_center_y = cropped_area_top_pixels + (cropped_area_image_height_pixels / 2.0);
let v_offset = -((crop_center_y / full_pano_height_pixels) - 0.5) * 180.0;
let horizon_y_crop = (full_pano_height_pixels / 2.0) - cropped_area_top_pixels;
let center_y_crop = cropped_area_image_height_pixels / 2.0;
let horizon_pixels = (horizon_y_crop - center_y_crop).round() as i32;
let projection = exif_info
.projection_type
.as_deref()
.map_or_else(Projection::default, |pt| {
if pt.trim().eq_ignore_ascii_case("cylindrical") {
Projection::Cylindrical
} else {
Projection::Equirectangular
}
});
PanoAngles {
haov,
vaov,
v_offset,
horizon_pixels,
north_offset: exif_info.pose_heading_degrees,
projection,
}
}
#[derive(Debug, Clone, Copy)]
pub struct DerivedAngles {
pub haov: f64,
pub vaov: f64,
}
#[must_use]
pub fn calc_cylindrical_pano_angles(
focal_length_35mm_eq: f64,
width: u32,
height: u32,
crop_factor: f64,
) -> Option<DerivedAngles> {
if focal_length_35mm_eq <= 0.0 || width == 0 || height == 0 {
return None;
}
let v_fov_lens_rad = 2.0 * (12.0 / focal_length_35mm_eq).atan();
let v_fov_lens_deg = v_fov_lens_rad.to_degrees();
let vaov = v_fov_lens_deg * crop_factor;
let vaov_rad = vaov.to_radians();
let aspect_ratio = f64::from(width) / f64::from(height);
let haov_rad = aspect_ratio * 2.0 * (vaov_rad / 2.0).tan();
let haov = haov_rad.to_degrees();
Some(DerivedAngles { haov, vaov })
}