use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use crate::bindings;
use crate::result::{MagickError, Result};
use crate::wand::MagickWand;
pub struct Image<'a> {
image: *mut bindings::Image,
phantom_data: PhantomData<&'a bindings::Image>,
}
impl Image<'_> {
pub (crate) fn new(img: *mut bindings::Image) -> Self {
Image {
image: img,
phantom_data: PhantomData,
}
}
pub (crate) unsafe fn get_ptr(&self) -> *mut bindings::Image {
self.image
}
}
fn pin(wand: &MagickWand, index: isize) {
debug_assert!(
index >= 0 && (index as usize) < wand.get_number_images(),
"frame index {index} out of bounds (count {})",
wand.get_number_images()
);
unsafe {
bindings::MagickSetIteratorIndex(wand.as_ptr(), index);
}
}
pub struct Images<'w> {
wand: &'w MagickWand,
}
impl<'w> Images<'w> {
pub(crate) fn new(wand: &'w MagickWand) -> Self {
wand.reset_iterator();
Images { wand }
}
pub fn count(&self) -> usize {
self.wand.get_number_images()
}
pub fn is_empty(&self) -> bool {
self.count() == 0
}
pub fn get(&self, index: usize) -> Option<ImageRef<'_>> {
if index < self.count() {
Some(ImageRef {
wand: self.wand,
index: index as isize,
})
} else {
None
}
}
pub fn first(&self) -> Option<ImageRef<'_>> {
self.get(0)
}
pub fn last(&self) -> Option<ImageRef<'_>> {
self.count().checked_sub(1).and_then(|i| self.get(i))
}
pub fn for_each(&self, mut f: impl FnMut(usize, ImageRef<'_>)) {
for index in 0..self.count() {
f(
index,
ImageRef {
wand: self.wand,
index: index as isize,
},
);
}
}
pub fn try_for_each(&self, mut f: impl FnMut(usize, ImageRef<'_>) -> Result<()>) -> Result<()> {
for index in 0..self.count() {
f(
index,
ImageRef {
wand: self.wand,
index: index as isize,
},
)?;
}
Ok(())
}
}
pub struct ImagesMut<'w> {
wand: &'w mut MagickWand,
}
impl<'w> ImagesMut<'w> {
pub(crate) fn new(wand: &'w mut MagickWand) -> Self {
wand.reset_iterator();
ImagesMut { wand }
}
pub fn count(&self) -> usize {
self.wand.get_number_images()
}
pub fn is_empty(&self) -> bool {
self.count() == 0
}
pub fn get(&mut self, index: usize) -> Option<ImageMut<'_>> {
if index < self.count() {
Some(ImageMut {
wand: &mut *self.wand,
index: index as isize,
})
} else {
None
}
}
pub fn first(&mut self) -> Option<ImageMut<'_>> {
self.get(0)
}
pub fn last(&mut self) -> Option<ImageMut<'_>> {
self.count().checked_sub(1).and_then(|i| self.get(i))
}
pub fn remove(&mut self, index: usize) -> Result<()> {
let count = self.count();
if index >= count {
return Err(MagickError(format!(
"image index {index} out of bounds (count {count})"
)));
}
pin(self.wand, index as isize);
self.wand.remove_image()
}
pub fn append(&mut self, other: &MagickWand) -> Result<()> {
self.wand.set_last_iterator();
self.wand.add_image(other)
}
pub fn for_each(&mut self, mut f: impl FnMut(usize, ImageMut<'_>)) {
for index in 0..self.count() {
f(
index,
ImageMut {
wand: &mut *self.wand,
index: index as isize,
},
);
}
}
pub fn try_for_each(
&mut self,
mut f: impl FnMut(usize, ImageMut<'_>) -> Result<()>,
) -> Result<()> {
for index in 0..self.count() {
f(
index,
ImageMut {
wand: &mut *self.wand,
index: index as isize,
},
)?;
}
Ok(())
}
}
pub struct ImageRef<'a> {
wand: &'a MagickWand,
index: isize,
}
macro_rules! frame_getters {
($($name:ident($($arg:ident: $ty:ty),*) -> $ret:ty;)*) => {
impl ImageRef<'_> {
$(
#[doc = concat!(
"Read this frame's value; see [`MagickWand::",
stringify!($name), "`]."
)]
pub fn $name(&self, $($arg: $ty),*) -> $ret {
pin(self.wand, self.index);
self.wand.$name($($arg),*)
}
)*
}
};
}
frame_getters! {
get_image_width() -> usize;
get_image_height() -> usize;
get_image_page() -> (usize, usize, isize, isize);
get_image_resolution() -> Result<(f64, f64)>;
get_image_range() -> Result<(f64, f64)>;
get_image_colors() -> usize;
get_image_alpha_channel() -> bool;
get_image_virtual_pixel_method() -> crate::VirtualPixelMethod;
get_image_pixel_color(x: isize, y: isize) -> Option<crate::PixelWand>;
get_image_histogram() -> Option<Vec<crate::PixelWand>>;
get_image_artifact(artifact: &str) -> Result<String>;
get_image_artifacts(pattern: &str) -> Result<Vec<String>>;
get_image_property(name: &str) -> Result<String>;
get_image_properties(pattern: &str) -> Result<Vec<String>>;
get_image_format() -> Result<String>;
get_image_filename() -> Result<String>;
get_image_compose() -> crate::CompositeOperator;
get_image_colorspace() -> crate::ColorspaceType;
get_image_compression() -> crate::CompressionType;
get_image_compression_quality() -> usize;
get_image_delay() -> usize;
get_image_depth() -> usize;
get_image_dispose() -> crate::DisposeType;
get_image_endian() -> crate::EndianType;
get_image_fuzz() -> f64;
get_image_gamma() -> f64;
get_image_gravity() -> crate::GravityType;
get_image_interlace_scheme() -> crate::InterlaceType;
get_image_interpolate_method() -> crate::PixelInterpolateMethod;
get_image_iterations() -> usize;
get_image_orientation() -> crate::OrientationType;
get_image_rendering_intent() -> crate::RenderingIntent;
get_image_scene() -> usize;
get_image_type() -> crate::ImageType;
get_image_units() -> crate::ResolutionType;
}
impl ImageRef<'_> {
pub fn get_image(&self) -> Result<Image<'_>> {
pin(self.wand, self.index);
self.wand.get_image()
}
}
pub struct ImageMut<'a> {
wand: &'a mut MagickWand,
index: isize,
}
impl Deref for ImageMut<'_> {
type Target = MagickWand;
fn deref(&self) -> &MagickWand {
pin(self.wand, self.index);
&*self.wand
}
}
impl DerefMut for ImageMut<'_> {
fn deref_mut(&mut self) -> &mut MagickWand {
pin(self.wand, self.index);
&mut *self.wand
}
}