Add a few more functions and typed
Adds `Image` type and a few image related functions.
This commit is contained in:
21
src/types/image.rs
Normal file
21
src/types/image.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
use crate::bindings;
|
||||||
|
|
||||||
|
pub struct Image<'a> {
|
||||||
|
image: *mut bindings::Image,
|
||||||
|
phantom_data: PhantomData<&'a bindings::Image>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Image<'_> {
|
||||||
|
pub unsafe fn new(img: *mut bindings::Image) -> Self {
|
||||||
|
Image {
|
||||||
|
image: img,
|
||||||
|
phantom_data: PhantomData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn get_ptr(&self) -> *mut bindings::Image {
|
||||||
|
self.image
|
||||||
|
}
|
||||||
|
}
|
||||||
35
src/types/layer_method.rs
Normal file
35
src/types/layer_method.rs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
use crate::bindings;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
#[repr(u32)]
|
||||||
|
pub enum LayerMethod {
|
||||||
|
Undefined = bindings::LayerMethod_UndefinedLayer,
|
||||||
|
Coalesce = bindings::LayerMethod_CoalesceLayer,
|
||||||
|
CompareAny = bindings::LayerMethod_CompareAnyLayer,
|
||||||
|
CompareClear = bindings::LayerMethod_CompareClearLayer,
|
||||||
|
CompareOverlay = bindings::LayerMethod_CompareOverlayLayer,
|
||||||
|
Dispose = bindings::LayerMethod_DisposeLayer,
|
||||||
|
Optimize = bindings::LayerMethod_OptimizeLayer,
|
||||||
|
OptimizeImage = bindings::LayerMethod_OptimizeImageLayer,
|
||||||
|
OptimizePlus = bindings::LayerMethod_OptimizePlusLayer,
|
||||||
|
OptimizeTrans = bindings::LayerMethod_OptimizeTransLayer,
|
||||||
|
RemoveDups = bindings::LayerMethod_RemoveDupsLayer,
|
||||||
|
RemoveZero = bindings::LayerMethod_RemoveZeroLayer,
|
||||||
|
Composite = bindings::LayerMethod_CompositeLayer,
|
||||||
|
Merge = bindings::LayerMethod_MergeLayer,
|
||||||
|
Flatten = bindings::LayerMethod_FlattenLayer,
|
||||||
|
Mosaic = bindings::LayerMethod_MosaicLayer,
|
||||||
|
TrimBounds = bindings::LayerMethod_TrimBoundsLayer,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for LayerMethod {
|
||||||
|
fn default() -> Self {
|
||||||
|
return LayerMethod::Undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<LayerMethod> for bindings::LayerMethod {
|
||||||
|
fn from(value: LayerMethod) -> Self {
|
||||||
|
return value as bindings::LayerMethod;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -15,9 +15,11 @@ mod fill_rule;
|
|||||||
mod filter_type;
|
mod filter_type;
|
||||||
mod geometry_info;
|
mod geometry_info;
|
||||||
mod gravity_type;
|
mod gravity_type;
|
||||||
|
mod image;
|
||||||
mod image_type;
|
mod image_type;
|
||||||
mod interlace_type;
|
mod interlace_type;
|
||||||
mod kernel;
|
mod kernel;
|
||||||
|
mod layer_method;
|
||||||
mod line_cap;
|
mod line_cap;
|
||||||
mod line_join;
|
mod line_join;
|
||||||
mod magick_evaluate_operator;
|
mod magick_evaluate_operator;
|
||||||
@ -50,9 +52,11 @@ pub use self::fill_rule::FillRule;
|
|||||||
pub use self::filter_type::FilterType;
|
pub use self::filter_type::FilterType;
|
||||||
pub use self::geometry_info::GeometryInfo;
|
pub use self::geometry_info::GeometryInfo;
|
||||||
pub use self::gravity_type::GravityType;
|
pub use self::gravity_type::GravityType;
|
||||||
|
pub use self::image::Image;
|
||||||
pub use self::image_type::ImageType;
|
pub use self::image_type::ImageType;
|
||||||
pub use self::interlace_type::InterlaceType;
|
pub use self::interlace_type::InterlaceType;
|
||||||
pub use self::kernel::*;
|
pub use self::kernel::*;
|
||||||
|
pub use self::layer_method::LayerMethod;
|
||||||
pub use self::line_cap::LineCap;
|
pub use self::line_cap::LineCap;
|
||||||
pub use self::line_join::LineJoin;
|
pub use self::line_join::LineJoin;
|
||||||
pub use self::magick_evaluate_operator::MagickEvaluateOperator;
|
pub use self::magick_evaluate_operator::MagickEvaluateOperator;
|
||||||
|
|||||||
@ -42,9 +42,11 @@ use crate::{
|
|||||||
EndianType,
|
EndianType,
|
||||||
FilterType,
|
FilterType,
|
||||||
GravityType,
|
GravityType,
|
||||||
|
Image,
|
||||||
ImageType,
|
ImageType,
|
||||||
InterlaceType,
|
InterlaceType,
|
||||||
KernelInfo,
|
KernelInfo,
|
||||||
|
LayerMethod,
|
||||||
MagickEvaluateOperator,
|
MagickEvaluateOperator,
|
||||||
MagickFunction,
|
MagickFunction,
|
||||||
MetricType,
|
MetricType,
|
||||||
@ -77,6 +79,21 @@ wand_common!(
|
|||||||
/// When the `MagickWand` is dropped, the ImageMagick wand will be
|
/// When the `MagickWand` is dropped, the ImageMagick wand will be
|
||||||
/// destroyed as well.
|
/// destroyed as well.
|
||||||
impl MagickWand {
|
impl MagickWand {
|
||||||
|
/// Creates new wand by cloning the image.
|
||||||
|
///
|
||||||
|
/// * `img`: the image.
|
||||||
|
pub fn new_from_image(img: &Image<'_>) -> Result<MagickWand> {
|
||||||
|
let result = unsafe {
|
||||||
|
bindings::NewMagickWandFromImage(img.get_ptr())
|
||||||
|
};
|
||||||
|
|
||||||
|
return if result.is_null() {
|
||||||
|
Err(MagickError("failed to create wand from image"))
|
||||||
|
} else {
|
||||||
|
Ok(MagickWand { wand: result })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new_image(&self, columns: usize, rows: usize, background: &PixelWand) -> Result<()> {
|
pub fn new_image(&self, columns: usize, rows: usize, background: &PixelWand) -> Result<()> {
|
||||||
match unsafe { bindings::MagickNewImage(self.wand, columns.into(), rows.into(), background.wand) } {
|
match unsafe { bindings::MagickNewImage(self.wand, columns.into(), rows.into(), background.wand) } {
|
||||||
MagickTrue => Ok(()),
|
MagickTrue => Ok(()),
|
||||||
@ -224,6 +241,37 @@ impl MagickWand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Composes all the image layers from the current given image onward to produce a single image
|
||||||
|
/// of the merged layers.
|
||||||
|
///
|
||||||
|
/// The inital canvas's size depends on the given LayerMethod, and is initialized using the
|
||||||
|
/// first images background color. The images are then composited onto that image in sequence
|
||||||
|
/// using the given composition that has been assigned to each individual image.
|
||||||
|
///
|
||||||
|
/// * `method`: the method of selecting the size of the initial canvas.
|
||||||
|
/// MergeLayer: Merge all layers onto a canvas just large enough to hold all the actual
|
||||||
|
/// images. The virtual canvas of the first image is preserved but otherwise ignored.
|
||||||
|
///
|
||||||
|
/// FlattenLayer: Use the virtual canvas size of first image. Images which fall outside
|
||||||
|
/// this canvas is clipped. This can be used to 'fill out' a given virtual canvas.
|
||||||
|
///
|
||||||
|
/// MosaicLayer: Start with the virtual canvas of the first image, enlarging left and right
|
||||||
|
/// edges to contain all images. Images with negative offsets will be clipped.
|
||||||
|
pub fn merge_image_layers(&self, method: LayerMethod) -> Result<MagickWand> {
|
||||||
|
let result = unsafe {
|
||||||
|
bindings::MagickMergeImageLayers(self.wand, method.into())
|
||||||
|
};
|
||||||
|
if result.is_null() {
|
||||||
|
return Err(MagickError("failed to merge image layres"));
|
||||||
|
}
|
||||||
|
return Ok(MagickWand { wand: result });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the number of images associated with a magick wand.
|
||||||
|
pub fn get_number_images(&self) -> usize {
|
||||||
|
return unsafe { bindings::MagickGetNumberImages(self.wand).into() };
|
||||||
|
}
|
||||||
|
|
||||||
/// Compare two images and return tuple `(distortion, diffImage)`
|
/// Compare two images and return tuple `(distortion, diffImage)`
|
||||||
/// `diffImage` is `None` if `distortion == 0`
|
/// `diffImage` is `None` if `distortion == 0`
|
||||||
pub fn compare_images(
|
pub fn compare_images(
|
||||||
@ -1540,6 +1588,64 @@ impl MagickWand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Applies a channel expression to the specified image. The expression
|
||||||
|
/// consists of one or more channels, either mnemonic or numeric (e.g. red, 1), separated by
|
||||||
|
/// actions as follows:
|
||||||
|
///
|
||||||
|
/// <=> exchange two channels (e.g. red<=>blue) => transfer a channel to another (e.g.
|
||||||
|
/// red=>green) , separate channel operations (e.g. red, green) | read channels from next input
|
||||||
|
/// image (e.g. red | green) ; write channels to next output image (e.g. red; green; blue) A
|
||||||
|
/// channel without a operation symbol implies extract. For example, to create 3 grayscale
|
||||||
|
/// images from the red, green, and blue channels of an image, use:
|
||||||
|
///
|
||||||
|
/// * `expression`: the expression.
|
||||||
|
pub fn channel_fx_image(&self, expression: &str) -> Result<MagickWand> {
|
||||||
|
let c_expression = CString::new(expression).map_err(|_| MagickError("artifact string contains null byte"))?;
|
||||||
|
|
||||||
|
let result = unsafe {
|
||||||
|
bindings::MagickChannelFxImage(
|
||||||
|
self.wand,
|
||||||
|
c_expression.as_ptr()
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
return if result.is_null() {
|
||||||
|
Err(MagickError("failed to apply expression to image"))
|
||||||
|
} else {
|
||||||
|
Ok(MagickWand{ wand: result })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Combines one or more images into a single image. The grayscale value of the pixels of each
|
||||||
|
/// image in the sequence is assigned in order to the specified channels of the combined image.
|
||||||
|
/// The typical ordering would be image 1 => Red, 2 => Green, 3 => Blue, etc.
|
||||||
|
///
|
||||||
|
/// * `colorspace`: the colorspace.
|
||||||
|
pub fn combine_images(&self, colorspace: ColorspaceType) -> Result<MagickWand> {
|
||||||
|
let result = unsafe {
|
||||||
|
bindings::MagickCombineImages(self.wand, colorspace.into())
|
||||||
|
};
|
||||||
|
|
||||||
|
return if result.is_null() {
|
||||||
|
Err(MagickError("failed to combine images"))
|
||||||
|
} else {
|
||||||
|
Ok(MagickWand{ wand: result })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the current image from the magick wand.
|
||||||
|
pub fn get_image<'wand>(&'wand self) -> Result<Image<'wand>> {
|
||||||
|
let result = unsafe {
|
||||||
|
bindings::GetImageFromMagickWand(self.wand)
|
||||||
|
};
|
||||||
|
|
||||||
|
return if result.is_null() {
|
||||||
|
Err(MagickError("no image in wand"))
|
||||||
|
} else {
|
||||||
|
unsafe { Ok(Image::new(result)) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mutations!(
|
mutations!(
|
||||||
/// Sets the image to the specified alpha level.
|
/// Sets the image to the specified alpha level.
|
||||||
MagickSetImageAlpha => set_image_alpha(alpha: f64)
|
MagickSetImageAlpha => set_image_alpha(alpha: f64)
|
||||||
|
|||||||
Reference in New Issue
Block a user