use openexr_sys as sys;
use crate::{
core::{
channel_list::Channel,
cppstd::CppString,
error::Error,
refptr::{OpaquePtr, Ref, RefMut},
LevelMode, LevelRoundingMode,
},
deep::deep_image_level::{DeepImageLevelRef, DeepImageLevelRefMut},
};
use imath_traits::Bound2;
type Result<T, E = Error> = std::result::Result<T, E>;
#[repr(transparent)]
pub struct DeepImage(pub(crate) *mut sys::Imf_DeepImage_t);
unsafe impl OpaquePtr for DeepImage {
type SysPointee = sys::Imf_DeepImage_t;
type Pointee = DeepImage;
}
pub type DeepImageRef<'a, P = DeepImage> = Ref<'a, P>;
pub type DeepImageRefMut<'a, P = DeepImage> = RefMut<'a, P>;
impl DeepImage {
pub fn new<B: Bound2<i32>>(
data_window: B,
level_mode: LevelMode,
level_rounding_mode: LevelRoundingMode,
) -> Result<DeepImage> {
let mut ptr = std::ptr::null_mut();
unsafe {
sys::Imf_DeepImage_ctor(
&mut ptr,
data_window.as_ptr() as *const sys::Imath_Box2i_t,
level_mode.into(),
level_rounding_mode.into(),
)
.into_result()?;
}
Ok(DeepImage(ptr))
}
pub fn level_mode(&self) -> LevelMode {
let mut v = sys::Imf_LevelMode(0);
unsafe {
sys::Imf_DeepImage_levelMode(self.0, &mut v);
v.into()
}
}
pub fn level_rounding_mode(&self) -> LevelRoundingMode {
let mut v = sys::Imf_LevelRoundingMode(0);
unsafe {
sys::Imf_DeepImage_levelRoundingMode(self.0, &mut v);
v.into()
}
}
pub fn num_levels(&self) -> Result<i32> {
let mut v = 0;
unsafe {
sys::Imf_DeepImage_numLevels(self.0, &mut v).into_result()?;
}
Ok(v)
}
pub fn num_x_levels(&self) -> i32 {
let mut v = 0;
unsafe {
sys::Imf_DeepImage_numXLevels(self.0, &mut v);
}
v
}
pub fn num_y_levels(&self) -> i32 {
let mut v = 0;
unsafe {
sys::Imf_DeepImage_numXLevels(self.0, &mut v);
}
v
}
pub fn data_window<B: Bound2<i32>>(&self) -> &B {
let mut ptr = std::ptr::null();
unsafe {
sys::Imf_DeepImage_dataWindow(self.0, &mut ptr);
&*(ptr as *const B)
}
}
pub fn data_window_for_level<B: Bound2<i32>>(
&self,
lx: i32,
ly: i32,
) -> Result<&B> {
let mut ptr = std::ptr::null();
unsafe {
sys::Imf_DeepImage_dataWindowForLevel(self.0, &mut ptr, lx, ly)
.into_result()?;
Ok(&*(ptr as *const B))
}
}
pub fn level_width(&self, lx: i32) -> Result<i32> {
let mut v = 0;
unsafe {
sys::Imf_DeepImage_levelWidth(self.0, &mut v, lx).into_result()?;
}
Ok(v)
}
pub fn level_height(&self, ly: i32) -> Result<i32> {
let mut v = 0;
unsafe {
sys::Imf_DeepImage_levelHeight(self.0, &mut v, ly).into_result()?;
}
Ok(v)
}
pub fn resize<B: Bound2<i32>>(
&mut self,
dw: B,
lm: LevelMode,
lrm: LevelRoundingMode,
) -> Result<()> {
unsafe {
sys::Imf_DeepImage_resize(
self.0,
dw.as_ptr() as *const sys::Imath_Box2i_t,
lm.into(),
lrm.into(),
)
.into_result()?;
}
Ok(())
}
pub fn shift_pixels(&mut self, dx: i32, dy: i32) -> Result<()> {
unsafe {
sys::Imf_DeepImage_shiftPixels(self.0, dx, dy).into_result()?;
}
Ok(())
}
pub fn insert_channel(
&mut self,
name: &str,
channel: &Channel,
) -> Result<()> {
unsafe {
let s = CppString::new(name);
sys::Imf_DeepImage_insertChannel(
self.0,
s.0,
channel.type_,
channel.x_sampling,
channel.y_sampling,
channel.p_linear,
)
.into_result()?;
}
Ok(())
}
pub fn erase_channel(&mut self, name: &str) {
unsafe {
let s = CppString::new(name);
sys::Imf_DeepImage_eraseChannel(self.0, s.0);
}
}
pub fn clear_channels(&mut self) {
unsafe {
sys::Imf_DeepImage_clearChannels(self.0);
}
}
pub fn rename_channel(
&mut self,
old_name: &str,
new_name: &str,
) -> Result<()> {
unsafe {
let sold = CppString::new(old_name);
let snew = CppString::new(new_name);
sys::Imf_DeepImage_renameChannel(self.0, sold.0, snew.0)
.into_result()?;
}
Ok(())
}
pub fn level(&self, lx: i32, ly: i32) -> Result<DeepImageLevelRef> {
let mut ptr = std::ptr::null();
unsafe {
sys::Imf_DeepImage_level_const(self.0, &mut ptr, lx, ly)
.into_result()?;
}
Ok(DeepImageLevelRef::new(ptr))
}
pub fn level_mut(&self, lx: i32, ly: i32) -> Result<DeepImageLevelRefMut> {
let mut ptr = std::ptr::null_mut();
unsafe {
sys::Imf_DeepImage_level(self.0, &mut ptr, lx, ly).into_result()?;
}
Ok(DeepImageLevelRefMut::new(ptr))
}
}
impl Default for DeepImage {
fn default() -> DeepImage {
let mut ptr = std::ptr::null_mut();
unsafe {
sys::Imf_DeepImage_default(&mut ptr);
}
DeepImage(ptr)
}
}
impl Drop for DeepImage {
fn drop(&mut self) {
unsafe {
sys::Imf_DeepImage_dtor(self.0);
}
}
}