Ran cargo fmt on the code base, looks better
cargo test passes
This commit is contained in:
58
build.rs
58
build.rs
@ -32,7 +32,10 @@ fn main() {
|
|||||||
if cfg!(target_os = "freebsd") {
|
if cfg!(target_os = "freebsd") {
|
||||||
// pkg_config does not seem to work properly on FreeBSD, so
|
// pkg_config does not seem to work properly on FreeBSD, so
|
||||||
// hard-code the builder settings for the time being.
|
// hard-code the builder settings for the time being.
|
||||||
env_var_set_default("IMAGE_MAGICK_INCLUDE_DIRS", "/usr/local/include/ImageMagick-7");
|
env_var_set_default(
|
||||||
|
"IMAGE_MAGICK_INCLUDE_DIRS",
|
||||||
|
"/usr/local/include/ImageMagick-7",
|
||||||
|
);
|
||||||
// Need to hack the linker flags as well.
|
// Need to hack the linker flags as well.
|
||||||
env_var_set_default("IMAGE_MAGICK_LIB_DIRS", "/usr/local/lib");
|
env_var_set_default("IMAGE_MAGICK_LIB_DIRS", "/usr/local/lib");
|
||||||
env_var_set_default("IMAGE_MAGICK_LIBS", "MagickWand-7");
|
env_var_set_default("IMAGE_MAGICK_LIBS", "MagickWand-7");
|
||||||
@ -41,14 +44,20 @@ fn main() {
|
|||||||
let lib_dirs = find_image_magick_lib_dirs();
|
let lib_dirs = find_image_magick_lib_dirs();
|
||||||
for d in &lib_dirs {
|
for d in &lib_dirs {
|
||||||
if !d.exists() {
|
if !d.exists() {
|
||||||
panic!("ImageMagick library directory does not exist: {}", d.to_string_lossy());
|
panic!(
|
||||||
|
"ImageMagick library directory does not exist: {}",
|
||||||
|
d.to_string_lossy()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
println!( "cargo:rustc-link-search=native={}", d.to_string_lossy());
|
println!("cargo:rustc-link-search=native={}", d.to_string_lossy());
|
||||||
}
|
}
|
||||||
let include_dirs = find_image_magick_include_dirs();
|
let include_dirs = find_image_magick_include_dirs();
|
||||||
for d in &include_dirs {
|
for d in &include_dirs {
|
||||||
if !d.exists() {
|
if !d.exists() {
|
||||||
panic!("ImageMagick include directory does not exist: {}", d.to_string_lossy());
|
panic!(
|
||||||
|
"ImageMagick include directory does not exist: {}",
|
||||||
|
d.to_string_lossy()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
println!("cargo:include={}", d.to_string_lossy());
|
println!("cargo:include={}", d.to_string_lossy());
|
||||||
}
|
}
|
||||||
@ -82,7 +91,9 @@ fn main() {
|
|||||||
// Create the header file that rust-bindgen needs as input.
|
// Create the header file that rust-bindgen needs as input.
|
||||||
let gen_h_path = out_dir.join("gen.h");
|
let gen_h_path = out_dir.join("gen.h");
|
||||||
let mut gen_h = File::create(&gen_h_path).expect("could not create file");
|
let mut gen_h = File::create(&gen_h_path).expect("could not create file");
|
||||||
gen_h.write_all(HEADER.as_bytes()).expect("could not write header file");
|
gen_h
|
||||||
|
.write_all(HEADER.as_bytes())
|
||||||
|
.expect("could not write header file");
|
||||||
|
|
||||||
// Geneate the bindings.
|
// Geneate the bindings.
|
||||||
let mut builder = bindgen::Builder::default()
|
let mut builder = bindgen::Builder::default()
|
||||||
@ -130,9 +141,7 @@ fn find_image_magick_lib_dirs() -> Vec<PathBuf> {
|
|||||||
env::var("IMAGE_MAGICK_LIB_DIRS")
|
env::var("IMAGE_MAGICK_LIB_DIRS")
|
||||||
.map(|x| x.split(":").map(PathBuf::from).collect::<Vec<PathBuf>>())
|
.map(|x| x.split(":").map(PathBuf::from).collect::<Vec<PathBuf>>())
|
||||||
.or_else(|_| Ok(vec![find_image_magick_dir()?.join("lib")]))
|
.or_else(|_| Ok(vec![find_image_magick_dir()?.join("lib")]))
|
||||||
.or_else(|_: env::VarError| -> Result<_, env::VarError> {
|
.or_else(|_: env::VarError| -> Result<_, env::VarError> { Ok(run_pkg_config().link_paths) })
|
||||||
Ok(run_pkg_config().link_paths)
|
|
||||||
})
|
|
||||||
.expect("Couldn't find ImageMagick library directory")
|
.expect("Couldn't find ImageMagick library directory")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,14 +152,12 @@ fn find_image_magick_include_dirs() -> Vec<PathBuf> {
|
|||||||
.or_else(|_| Ok(vec![find_image_magick_dir()?.join("include")]))
|
.or_else(|_| Ok(vec![find_image_magick_dir()?.join("include")]))
|
||||||
.or_else(|_: env::VarError| -> Result<_, env::VarError> {
|
.or_else(|_: env::VarError| -> Result<_, env::VarError> {
|
||||||
Ok(run_pkg_config().include_paths)
|
Ok(run_pkg_config().include_paths)
|
||||||
})
|
}).expect("Couldn't find ImageMagick include directory")
|
||||||
.expect("Couldn't find ImageMagick include directory")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_image_magick_dir() -> Result<PathBuf, env::VarError> {
|
fn find_image_magick_dir() -> Result<PathBuf, env::VarError> {
|
||||||
println!("cargo:rerun-if-env-changed=IMAGE_MAGICK_DIR");
|
println!("cargo:rerun-if-env-changed=IMAGE_MAGICK_DIR");
|
||||||
env::var("IMAGE_MAGICK_DIR")
|
env::var("IMAGE_MAGICK_DIR").map(PathBuf::from)
|
||||||
.map(PathBuf::from)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn determine_mode<T: AsRef<str>>(libdirs: &Vec<PathBuf>, libs: &[T]) -> &'static str {
|
fn determine_mode<T: AsRef<str>>(libdirs: &Vec<PathBuf>, libs: &[T]) -> &'static str {
|
||||||
@ -164,19 +171,21 @@ fn determine_mode<T: AsRef<str>>(libdirs: &Vec<PathBuf>, libs: &[T]) -> &'static
|
|||||||
|
|
||||||
// See what files we actually have to link against, and see what our
|
// See what files we actually have to link against, and see what our
|
||||||
// possibilities even are.
|
// possibilities even are.
|
||||||
let files = libdirs.into_iter().flat_map(|d| d.read_dir().unwrap())
|
let files = libdirs
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|d| d.read_dir().unwrap())
|
||||||
.map(|e| e.unwrap())
|
.map(|e| e.unwrap())
|
||||||
.map(|e| e.file_name())
|
.map(|e| e.file_name())
|
||||||
.filter_map(|e| e.into_string().ok())
|
.filter_map(|e| e.into_string().ok())
|
||||||
.collect::<HashSet<_>>();
|
.collect::<HashSet<_>>();
|
||||||
let can_static = libs.iter().all(|l| {
|
let can_static = libs.iter().all(|l| {
|
||||||
files.contains(&format!("lib{}.a", l.as_ref())) ||
|
files.contains(&format!("lib{}.a", l.as_ref()))
|
||||||
files.contains(&format!("{}.lib", l.as_ref()))
|
|| files.contains(&format!("{}.lib", l.as_ref()))
|
||||||
});
|
});
|
||||||
let can_dylib = libs.iter().all(|l| {
|
let can_dylib = libs.iter().all(|l| {
|
||||||
files.contains(&format!("lib{}.so", l.as_ref())) ||
|
files.contains(&format!("lib{}.so", l.as_ref()))
|
||||||
files.contains(&format!("{}.dll", l.as_ref())) ||
|
|| files.contains(&format!("{}.dll", l.as_ref()))
|
||||||
files.contains(&format!("lib{}.dylib", l.as_ref()))
|
|| files.contains(&format!("lib{}.dylib", l.as_ref()))
|
||||||
});
|
});
|
||||||
|
|
||||||
match (can_static, can_dylib) {
|
match (can_static, can_dylib) {
|
||||||
@ -211,12 +220,19 @@ fn run_pkg_config() -> pkg_config::Library {
|
|||||||
if !Command::new("pkg-config")
|
if !Command::new("pkg-config")
|
||||||
.arg(format!("--max-version={}", MAX_VERSION))
|
.arg(format!("--max-version={}", MAX_VERSION))
|
||||||
.arg("MagickWand")
|
.arg("MagickWand")
|
||||||
.status().unwrap().success() {
|
.status()
|
||||||
panic!(format!("MagickWand version must be no higher than {}", MAX_VERSION));
|
.unwrap()
|
||||||
|
.success()
|
||||||
|
{
|
||||||
|
panic!(format!(
|
||||||
|
"MagickWand version must be no higher than {}",
|
||||||
|
MAX_VERSION
|
||||||
|
));
|
||||||
}
|
}
|
||||||
// We have to split the version check and the cflags/libs check because
|
// We have to split the version check and the cflags/libs check because
|
||||||
// you can't do both at the same time on RHEL (apparently).
|
// you can't do both at the same time on RHEL (apparently).
|
||||||
pkg_config::Config::new()
|
pkg_config::Config::new()
|
||||||
.cargo_metadata(false)
|
.cargo_metadata(false)
|
||||||
.probe("MagickWand").unwrap()
|
.probe("MagickWand")
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,7 +33,10 @@ pub trait ToMagick<T> {
|
|||||||
fn to_magick(self) -> T;
|
fn to_magick(self) -> T;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, E> ToMagick<T> for E where T: FromRust<E> {
|
impl<T, E> ToMagick<T> for E
|
||||||
|
where
|
||||||
|
T: FromRust<E>,
|
||||||
|
{
|
||||||
fn to_magick(self) -> T {
|
fn to_magick(self) -> T {
|
||||||
<T as FromRust<E>>::from_rust(self)
|
<T as FromRust<E>>::from_rust(self)
|
||||||
}
|
}
|
||||||
|
|||||||
19
src/lib.rs
19
src/lib.rs
@ -32,13 +32,15 @@
|
|||||||
|
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
|
|
||||||
mod wand;
|
|
||||||
mod conversions;
|
mod conversions;
|
||||||
|
mod wand;
|
||||||
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
|
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
|
||||||
|
|
||||||
pub use wand::*;
|
pub use bindings::{
|
||||||
pub use bindings::{MetricType, FilterType, ColorspaceType, DitherMethod, CompositeOperator, GravityType};
|
ColorspaceType, CompositeOperator, DitherMethod, FilterType, GravityType, MetricType,
|
||||||
|
};
|
||||||
pub use conversions::ToMagick;
|
pub use conversions::ToMagick;
|
||||||
|
pub use wand::*;
|
||||||
|
|
||||||
use libc::size_t;
|
use libc::size_t;
|
||||||
#[cfg(not(target_os = "freebsd"))]
|
#[cfg(not(target_os = "freebsd"))]
|
||||||
@ -50,7 +52,7 @@ pub fn magick_wand_genesis() {
|
|||||||
unsafe {
|
unsafe {
|
||||||
match bindings::IsMagickWandInstantiated() {
|
match bindings::IsMagickWandInstantiated() {
|
||||||
bindings::MagickBooleanType_MagickTrue => (),
|
bindings::MagickBooleanType_MagickTrue => (),
|
||||||
_ => bindings::MagickWandGenesis()
|
_ => bindings::MagickWandGenesis(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -61,15 +63,17 @@ pub fn magick_wand_terminus() {
|
|||||||
unsafe {
|
unsafe {
|
||||||
match bindings::IsMagickWandInstantiated() {
|
match bindings::IsMagickWandInstantiated() {
|
||||||
bindings::MagickBooleanType_MagickTrue => bindings::MagickWandTerminus(),
|
bindings::MagickBooleanType_MagickTrue => bindings::MagickWandTerminus(),
|
||||||
_ => ()
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn magick_query_fonts(pattern: &str) -> Result<Vec<String>, &'static str> {
|
pub fn magick_query_fonts(pattern: &str) -> Result<Vec<String>, &'static str> {
|
||||||
let mut number_fonts: size_t = 0;
|
let mut number_fonts: size_t = 0;
|
||||||
let c_string = try!(::std::ffi::CString::new(pattern).map_err(|_| "could not convert to cstring"));
|
let c_string =
|
||||||
let ptr = unsafe { bindings::MagickQueryFonts(c_string.as_ptr(), &mut number_fonts as *mut size_t) };
|
try!(::std::ffi::CString::new(pattern).map_err(|_| "could not convert to cstring"));
|
||||||
|
let ptr =
|
||||||
|
unsafe { bindings::MagickQueryFonts(c_string.as_ptr(), &mut number_fonts as *mut size_t) };
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
Err("null ptr returned by magick_query_fonts")
|
Err("null ptr returned by magick_query_fonts")
|
||||||
} else {
|
} else {
|
||||||
@ -81,5 +85,4 @@ pub fn magick_query_fonts(pattern: &str) -> Result<Vec<String>, &'static str> {
|
|||||||
}
|
}
|
||||||
Ok(v)
|
Ok(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,18 +13,24 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
use std::fmt;
|
use bindings;
|
||||||
use std::ffi::{CStr, CString};
|
|
||||||
use ::bindings;
|
|
||||||
#[cfg(target_os = "freebsd")]
|
#[cfg(target_os = "freebsd")]
|
||||||
use libc::size_t;
|
use libc::size_t;
|
||||||
#[cfg(not(target_os = "freebsd"))]
|
#[cfg(not(target_os = "freebsd"))]
|
||||||
use ::size_t;
|
use size_t;
|
||||||
|
use std::ffi::{CStr, CString};
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
wand_common!(
|
wand_common!(
|
||||||
DrawingWand,
|
DrawingWand,
|
||||||
NewDrawingWand, ClearDrawingWand, IsDrawingWand, CloneDrawingWand, DestroyDrawingWand,
|
NewDrawingWand,
|
||||||
DrawClearException, DrawGetExceptionType, DrawGetException
|
ClearDrawingWand,
|
||||||
|
IsDrawingWand,
|
||||||
|
CloneDrawingWand,
|
||||||
|
DestroyDrawingWand,
|
||||||
|
DrawClearException,
|
||||||
|
DrawGetExceptionType,
|
||||||
|
DrawGetException
|
||||||
);
|
);
|
||||||
|
|
||||||
impl DrawingWand {
|
impl DrawingWand {
|
||||||
@ -42,7 +48,10 @@ impl DrawingWand {
|
|||||||
);
|
);
|
||||||
|
|
||||||
string_set_get_unchecked!(
|
string_set_get_unchecked!(
|
||||||
get_text_encoding, set_text_encoding, DrawGetTextEncoding, DrawSetTextEncoding
|
get_text_encoding,
|
||||||
|
set_text_encoding,
|
||||||
|
DrawGetTextEncoding,
|
||||||
|
DrawSetTextEncoding
|
||||||
);
|
);
|
||||||
|
|
||||||
pixel_set_get!(
|
pixel_set_get!(
|
||||||
|
|||||||
@ -19,13 +19,13 @@ macro_rules! wand_common {
|
|||||||
$clear_exc:ident, $get_exc_type:ident, $get_exc:ident
|
$clear_exc:ident, $get_exc_type:ident, $get_exc:ident
|
||||||
) => {
|
) => {
|
||||||
pub struct $wand {
|
pub struct $wand {
|
||||||
pub wand: *mut ::bindings::$wand
|
pub wand: *mut ::bindings::$wand,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl $wand {
|
impl $wand {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
$wand {
|
$wand {
|
||||||
wand: unsafe { ::bindings::$new_wand() }
|
wand: unsafe { ::bindings::$new_wand() },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ macro_rules! wand_common {
|
|||||||
fn clear_exception(&mut self) -> Result<(), &'static str> {
|
fn clear_exception(&mut self) -> Result<(), &'static str> {
|
||||||
match unsafe { ::bindings::$clear_exc(self.wand) } {
|
match unsafe { ::bindings::$clear_exc(self.wand) } {
|
||||||
::bindings::MagickBooleanType_MagickTrue => Ok(()),
|
::bindings::MagickBooleanType_MagickTrue => Ok(()),
|
||||||
_ => Err(concat!("failed to clear", stringify!($wand), "exception"))
|
_ => Err(concat!("failed to clear", stringify!($wand), "exception")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,11 +45,16 @@ macro_rules! wand_common {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_exception(&self) -> Result<(String, ::bindings::ExceptionType), &'static str> {
|
fn get_exception(&self) -> Result<(String, ::bindings::ExceptionType), &'static str> {
|
||||||
let mut severity: ::bindings::ExceptionType = ::bindings::ExceptionType_UndefinedException;
|
let mut severity: ::bindings::ExceptionType =
|
||||||
|
::bindings::ExceptionType_UndefinedException;
|
||||||
// TODO: memory management
|
// TODO: memory management
|
||||||
let ptr = unsafe { ::bindings::$get_exc(self.wand, &mut severity as *mut _) };
|
let ptr = unsafe { ::bindings::$get_exc(self.wand, &mut severity as *mut _) };
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
Err(concat!("null ptr returned by", stringify!($wand), "get_exception"))
|
Err(concat!(
|
||||||
|
"null ptr returned by",
|
||||||
|
stringify!($wand),
|
||||||
|
"get_exception"
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
let c_str = unsafe { CStr::from_ptr(ptr) };
|
let c_str = unsafe { CStr::from_ptr(ptr) };
|
||||||
Ok((c_str.to_string_lossy().into_owned(), severity))
|
Ok((c_str.to_string_lossy().into_owned(), severity))
|
||||||
@ -59,7 +64,7 @@ macro_rules! wand_common {
|
|||||||
pub fn is_wand(&self) -> Result<(), &'static str> {
|
pub fn is_wand(&self) -> Result<(), &'static str> {
|
||||||
match unsafe { ::bindings::$is_wand(self.wand) } {
|
match unsafe { ::bindings::$is_wand(self.wand) } {
|
||||||
::bindings::MagickBooleanType_MagickTrue => Ok(()),
|
::bindings::MagickBooleanType_MagickTrue => Ok(()),
|
||||||
_ => Err(concat!(stringify!($wand), " not a wand"))
|
_ => Err(concat!(stringify!($wand), " not a wand")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -67,7 +72,7 @@ macro_rules! wand_common {
|
|||||||
impl Clone for $wand {
|
impl Clone for $wand {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
$wand {
|
$wand {
|
||||||
wand: unsafe { ::bindings::$clone(self.wand) }
|
wand: unsafe { ::bindings::$clone(self.wand) },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -80,7 +85,7 @@ macro_rules! wand_common {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! get {
|
macro_rules! get {
|
||||||
@ -165,7 +170,6 @@ macro_rules! string_set_get {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
macro_rules! string_set_get_unchecked {
|
macro_rules! string_set_get_unchecked {
|
||||||
($($get:ident, $set:ident, $c_get:ident, $c_set:ident )*) => {
|
($($get:ident, $set:ident, $c_get:ident, $c_set:ident )*) => {
|
||||||
$(
|
$(
|
||||||
@ -183,7 +187,6 @@ macro_rules! string_set_get_unchecked {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
macro_rules! pixel_set_get {
|
macro_rules! pixel_set_get {
|
||||||
($($get:ident, $set:ident, $c_get:ident, $c_set:ident )*) => {
|
($($get:ident, $set:ident, $c_get:ident, $c_set:ident )*) => {
|
||||||
$(
|
$(
|
||||||
|
|||||||
@ -13,22 +13,28 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
use std::{fmt, ptr, slice};
|
use libc::c_void;
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
use libc::{c_void};
|
use std::{fmt, ptr, slice};
|
||||||
|
|
||||||
|
use super::{DrawingWand, PixelWand};
|
||||||
|
use bindings;
|
||||||
|
use conversions::*;
|
||||||
#[cfg(target_os = "freebsd")]
|
#[cfg(target_os = "freebsd")]
|
||||||
use libc::{size_t, ssize_t};
|
use libc::{size_t, ssize_t};
|
||||||
#[cfg(not(target_os = "freebsd"))]
|
#[cfg(not(target_os = "freebsd"))]
|
||||||
use ::{size_t, ssize_t};
|
use {size_t, ssize_t};
|
||||||
use ::bindings;
|
|
||||||
use ::conversions::*;
|
|
||||||
use super::{DrawingWand, PixelWand};
|
|
||||||
|
|
||||||
wand_common!(
|
wand_common!(
|
||||||
MagickWand,
|
MagickWand,
|
||||||
NewMagickWand, ClearMagickWand, IsMagickWand, CloneMagickWand, DestroyMagickWand,
|
NewMagickWand,
|
||||||
MagickClearException, MagickGetExceptionType, MagickGetException
|
ClearMagickWand,
|
||||||
|
IsMagickWand,
|
||||||
|
CloneMagickWand,
|
||||||
|
DestroyMagickWand,
|
||||||
|
MagickClearException,
|
||||||
|
MagickGetExceptionType,
|
||||||
|
MagickGetException
|
||||||
);
|
);
|
||||||
|
|
||||||
/// MagickWand is a Rustic wrapper to the Rust bindings to ImageMagick.
|
/// MagickWand is a Rustic wrapper to the Rust bindings to ImageMagick.
|
||||||
@ -38,8 +44,12 @@ 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 {
|
||||||
|
pub fn new_image(
|
||||||
pub fn new_image(&self, columns: size_t, rows: size_t, pixel_wand: &PixelWand) -> Result<(), &'static str> {
|
&self,
|
||||||
|
columns: size_t,
|
||||||
|
rows: size_t,
|
||||||
|
pixel_wand: &PixelWand,
|
||||||
|
) -> Result<(), &'static str> {
|
||||||
match unsafe { bindings::MagickNewImage(self.wand, columns, rows, pixel_wand.wand) } {
|
match unsafe { bindings::MagickNewImage(self.wand, columns, rows, pixel_wand.wand) } {
|
||||||
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
||||||
_ => Err("Could not create image"),
|
_ => Err("Could not create image"),
|
||||||
@ -49,20 +59,35 @@ impl MagickWand {
|
|||||||
pub fn set_option(&mut self, key: &str, value: &str) -> Result<(), &'static str> {
|
pub fn set_option(&mut self, key: &str, value: &str) -> Result<(), &'static str> {
|
||||||
let c_key = CString::new(key).unwrap();
|
let c_key = CString::new(key).unwrap();
|
||||||
let c_value = CString::new(value).unwrap();
|
let c_value = CString::new(value).unwrap();
|
||||||
let result = unsafe {
|
let result =
|
||||||
bindings::MagickSetOption(self.wand, c_key.as_ptr(), c_value.as_ptr())
|
unsafe { bindings::MagickSetOption(self.wand, c_key.as_ptr(), c_value.as_ptr()) };
|
||||||
};
|
|
||||||
match result {
|
match result {
|
||||||
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
||||||
_ => Err("failed to set option"),
|
_ => Err("failed to set option"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn annotate_image(&mut self, drawing_wand: &DrawingWand, x: f64, y: f64, angle: f64, text: &str) -> Result<(), &'static str> {
|
pub fn annotate_image(
|
||||||
|
&mut self,
|
||||||
|
drawing_wand: &DrawingWand,
|
||||||
|
x: f64,
|
||||||
|
y: f64,
|
||||||
|
angle: f64,
|
||||||
|
text: &str,
|
||||||
|
) -> Result<(), &'static str> {
|
||||||
let c_string = try!(CString::new(text).map_err(|_| "could not convert to cstring"));
|
let c_string = try!(CString::new(text).map_err(|_| "could not convert to cstring"));
|
||||||
match unsafe { bindings::MagickAnnotateImage(self.wand, drawing_wand.wand, x, y, angle, c_string.as_ptr() as *const _) } {
|
match unsafe {
|
||||||
|
bindings::MagickAnnotateImage(
|
||||||
|
self.wand,
|
||||||
|
drawing_wand.wand,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
angle,
|
||||||
|
c_string.as_ptr() as *const _,
|
||||||
|
)
|
||||||
|
} {
|
||||||
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
||||||
_ => Err("unable to annotate image")
|
_ => Err("unable to annotate image"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,48 +95,43 @@ impl MagickWand {
|
|||||||
pub fn add_image(&mut self, other_wand: &MagickWand) -> Result<(), &'static str> {
|
pub fn add_image(&mut self, other_wand: &MagickWand) -> Result<(), &'static str> {
|
||||||
match unsafe { bindings::MagickAddImage(self.wand, other_wand.wand) } {
|
match unsafe { bindings::MagickAddImage(self.wand, other_wand.wand) } {
|
||||||
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
||||||
_ => Err("unable to add images from another wand")
|
_ => Err("unable to add images from another wand"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn append_all(&mut self, stack: bool) -> MagickWand {
|
pub fn append_all(&mut self, stack: bool) -> MagickWand {
|
||||||
unsafe { bindings::MagickResetIterator(self.wand) };
|
unsafe { bindings::MagickResetIterator(self.wand) };
|
||||||
MagickWand {
|
MagickWand {
|
||||||
wand: unsafe { bindings::MagickAppendImages(self.wand, stack.to_magick()) }
|
wand: unsafe { bindings::MagickAppendImages(self.wand, stack.to_magick()) },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn label_image(&self, label: &str) -> Result<(), &'static str> {
|
pub fn label_image(&self, label: &str) -> Result<(), &'static str> {
|
||||||
let c_label = CString::new(label).unwrap();
|
let c_label = CString::new(label).unwrap();
|
||||||
let result = unsafe {
|
let result = unsafe { bindings::MagickLabelImage(self.wand, c_label.as_ptr()) };
|
||||||
bindings::MagickLabelImage(self.wand, c_label.as_ptr())
|
|
||||||
};
|
|
||||||
match result {
|
match result {
|
||||||
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
||||||
_ => Err("failed to add label")
|
_ => Err("failed to add label"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_images(&self, path: &str, adjoin: bool) -> Result<(), &'static str> {
|
pub fn write_images(&self, path: &str, adjoin: bool) -> Result<(), &'static str> {
|
||||||
let c_name = CString::new(path).unwrap();
|
let c_name = CString::new(path).unwrap();
|
||||||
let result = unsafe {
|
let result =
|
||||||
bindings::MagickWriteImages(self.wand, c_name.as_ptr(), adjoin.to_magick())
|
unsafe { bindings::MagickWriteImages(self.wand, c_name.as_ptr(), adjoin.to_magick()) };
|
||||||
};
|
|
||||||
match result {
|
match result {
|
||||||
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
||||||
_ => Err("failed to write images")
|
_ => Err("failed to write images"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read the image data from the named file.
|
/// Read the image data from the named file.
|
||||||
pub fn read_image(&self, path: &str) -> Result<(), &'static str> {
|
pub fn read_image(&self, path: &str) -> Result<(), &'static str> {
|
||||||
let c_name = CString::new(path).unwrap();
|
let c_name = CString::new(path).unwrap();
|
||||||
let result = unsafe {
|
let result = unsafe { bindings::MagickReadImage(self.wand, c_name.as_ptr()) };
|
||||||
bindings::MagickReadImage(self.wand, c_name.as_ptr())
|
|
||||||
};
|
|
||||||
match result {
|
match result {
|
||||||
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
||||||
_ => Err("failed to read image")
|
_ => Err("failed to read image"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,11 +141,14 @@ impl MagickWand {
|
|||||||
let size = int_slice.len();
|
let size = int_slice.len();
|
||||||
let result = unsafe {
|
let result = unsafe {
|
||||||
bindings::MagickReadImageBlob(
|
bindings::MagickReadImageBlob(
|
||||||
self.wand, int_slice.as_ptr() as *const c_void, size as size_t)
|
self.wand,
|
||||||
|
int_slice.as_ptr() as *const c_void,
|
||||||
|
size as size_t,
|
||||||
|
)
|
||||||
};
|
};
|
||||||
match result {
|
match result {
|
||||||
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
||||||
_ => Err("failed to read image")
|
_ => Err("failed to read image"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,12 +156,10 @@ impl MagickWand {
|
|||||||
/// without reading data.
|
/// without reading data.
|
||||||
pub fn ping_image(&self, path: &str) -> Result<(), &'static str> {
|
pub fn ping_image(&self, path: &str) -> Result<(), &'static str> {
|
||||||
let c_name = CString::new(path).unwrap();
|
let c_name = CString::new(path).unwrap();
|
||||||
let result = unsafe {
|
let result = unsafe { bindings::MagickPingImage(self.wand, c_name.as_ptr()) };
|
||||||
bindings::MagickPingImage(self.wand, c_name.as_ptr())
|
|
||||||
};
|
|
||||||
match result {
|
match result {
|
||||||
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
||||||
_ => Err("failed to ping image")
|
_ => Err("failed to ping image"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,105 +170,127 @@ impl MagickWand {
|
|||||||
let size = int_slice.len();
|
let size = int_slice.len();
|
||||||
let result = unsafe {
|
let result = unsafe {
|
||||||
bindings::MagickPingImageBlob(
|
bindings::MagickPingImageBlob(
|
||||||
self.wand, int_slice.as_ptr() as *const c_void, size as size_t)
|
self.wand,
|
||||||
|
int_slice.as_ptr() as *const c_void,
|
||||||
|
size as size_t,
|
||||||
|
)
|
||||||
};
|
};
|
||||||
match result {
|
match result {
|
||||||
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
||||||
_ => Err("failed to ping image")
|
_ => Err("failed to ping image"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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(&self, reference: &MagickWand, metric: bindings::MetricType) -> (f64, Option<MagickWand>) {
|
pub fn compare_images(
|
||||||
|
&self,
|
||||||
|
reference: &MagickWand,
|
||||||
|
metric: bindings::MetricType,
|
||||||
|
) -> (f64, Option<MagickWand>) {
|
||||||
let mut distortion: f64 = 0.0;
|
let mut distortion: f64 = 0.0;
|
||||||
let result = unsafe {
|
let result = unsafe {
|
||||||
bindings::MagickCompareImages(self.wand, reference.wand, metric, &mut distortion)
|
bindings::MagickCompareImages(self.wand, reference.wand, metric, &mut distortion)
|
||||||
};
|
};
|
||||||
let wand = if result.is_null() {
|
let wand = if result.is_null() {
|
||||||
None
|
None
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
Some(MagickWand { wand: result })
|
Some(MagickWand { wand: result })
|
||||||
};
|
};
|
||||||
(distortion, wand)
|
(distortion, wand)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compose another image onto self at (x, y) using composition_operator
|
/// Compose another image onto self at (x, y) using composition_operator
|
||||||
pub fn compose_images(&self, reference: &MagickWand, composition_operator: bindings::CompositeOperator, clip_to_self: bool, x: isize, y: isize) -> Result<(), &'static str> {
|
pub fn compose_images(
|
||||||
|
&self,
|
||||||
|
reference: &MagickWand,
|
||||||
|
composition_operator: bindings::CompositeOperator,
|
||||||
|
clip_to_self: bool,
|
||||||
|
x: isize,
|
||||||
|
y: isize,
|
||||||
|
) -> Result<(), &'static str> {
|
||||||
let native_clip_to_self = if clip_to_self {
|
let native_clip_to_self = if clip_to_self {
|
||||||
bindings::MagickBooleanType_MagickTrue
|
bindings::MagickBooleanType_MagickTrue
|
||||||
} else {
|
} else {
|
||||||
bindings::MagickBooleanType_MagickFalse
|
bindings::MagickBooleanType_MagickFalse
|
||||||
};
|
};
|
||||||
let result = unsafe {
|
let result = unsafe {
|
||||||
bindings::MagickCompositeImage(self.wand, reference.wand,
|
bindings::MagickCompositeImage(
|
||||||
composition_operator, native_clip_to_self, x, y
|
self.wand,
|
||||||
|
reference.wand,
|
||||||
|
composition_operator,
|
||||||
|
native_clip_to_self,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
match result {
|
match result {
|
||||||
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
||||||
_ => Err("failed to compose images")
|
_ => Err("failed to compose images"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extend the image as defined by the geometry, gravity, and wand background color. Set the
|
/// Extend the image as defined by the geometry, gravity, and wand background color. Set the
|
||||||
/// (x,y) offset of the geometry to move the original wand relative to the extended wand.
|
/// (x,y) offset of the geometry to move the original wand relative to the extended wand.
|
||||||
pub fn extend_image(&self, width: usize, height: usize, x: isize, y: isize) -> Result<(), &'static str> {
|
pub fn extend_image(
|
||||||
let result = unsafe {
|
&self,
|
||||||
bindings::MagickExtentImage(self.wand, width, height, x, y)
|
width: usize,
|
||||||
};
|
height: usize,
|
||||||
|
x: isize,
|
||||||
|
y: isize,
|
||||||
|
) -> Result<(), &'static str> {
|
||||||
|
let result = unsafe { bindings::MagickExtentImage(self.wand, width, height, x, y) };
|
||||||
match result {
|
match result {
|
||||||
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
||||||
_ => Err("failed to extend image")
|
_ => Err("failed to extend image"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn profile_image<'a, T: Into<Option<&'a [u8]>>>(&self, name: &str, profile: T) -> Result<(), &'static str> {
|
pub fn profile_image<'a, T: Into<Option<&'a [u8]>>>(
|
||||||
|
&self,
|
||||||
|
name: &str,
|
||||||
|
profile: T,
|
||||||
|
) -> Result<(), &'static str> {
|
||||||
let c_name = CString::new(name).unwrap();
|
let c_name = CString::new(name).unwrap();
|
||||||
let result = unsafe {
|
let result = unsafe {
|
||||||
let profile = profile.into();
|
let profile = profile.into();
|
||||||
let profile_ptr = match profile {
|
let profile_ptr = match profile {
|
||||||
Some(data) => data.as_ptr(),
|
Some(data) => data.as_ptr(),
|
||||||
None => ptr::null()
|
None => ptr::null(),
|
||||||
} as *const c_void;
|
} as *const c_void;
|
||||||
let profile_len = match profile {
|
let profile_len = match profile {
|
||||||
Some(data) => data.len(),
|
Some(data) => data.len(),
|
||||||
None => 0
|
None => 0,
|
||||||
};
|
};
|
||||||
bindings::MagickProfileImage(self.wand, c_name.as_ptr(), profile_ptr, profile_len)
|
bindings::MagickProfileImage(self.wand, c_name.as_ptr(), profile_ptr, profile_len)
|
||||||
};
|
};
|
||||||
match result {
|
match result {
|
||||||
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
||||||
_ => Err("failed to profile image")
|
_ => Err("failed to profile image"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn flip_image(&self) -> Result<(), &'static str> {
|
pub fn flip_image(&self) -> Result<(), &'static str> {
|
||||||
let result = unsafe {
|
let result = unsafe { bindings::MagickFlipImage(self.wand) };
|
||||||
bindings::MagickFlipImage(self.wand)
|
|
||||||
};
|
|
||||||
match result {
|
match result {
|
||||||
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
||||||
_ => Err("failed to flip image")
|
_ => Err("failed to flip image"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn flop_image(&self) -> Result<(), &'static str> {
|
pub fn flop_image(&self) -> Result<(), &'static str> {
|
||||||
let result = unsafe {
|
let result = unsafe { bindings::MagickFlopImage(self.wand) };
|
||||||
bindings::MagickFlopImage(self.wand)
|
|
||||||
};
|
|
||||||
match result {
|
match result {
|
||||||
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
||||||
_ => Err("failed to flip image")
|
_ => Err("failed to flip image"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adaptively resize the currently selected image.
|
/// Adaptively resize the currently selected image.
|
||||||
pub fn adaptive_resize_image(&self, width: usize, height: usize) -> Result<(), &'static str> {
|
pub fn adaptive_resize_image(&self, width: usize, height: usize) -> Result<(), &'static str> {
|
||||||
match unsafe { bindings::MagickAdaptiveResizeImage(self.wand, width, height)} {
|
match unsafe { bindings::MagickAdaptiveResizeImage(self.wand, width, height) } {
|
||||||
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
||||||
_ => Err("failed to adaptive-resize image")
|
_ => Err("failed to adaptive-resize image"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,33 +299,27 @@ impl MagickWand {
|
|||||||
pub fn rotate_image(&self, background: &PixelWand, degrees: f64) -> Result<(), &'static str> {
|
pub fn rotate_image(&self, background: &PixelWand, degrees: f64) -> Result<(), &'static str> {
|
||||||
match unsafe { bindings::MagickRotateImage(self.wand, background.wand, degrees) } {
|
match unsafe { bindings::MagickRotateImage(self.wand, background.wand, degrees) } {
|
||||||
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
||||||
_ => Err("failed to rotate image")
|
_ => Err("failed to rotate image"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trim the image removing the backround color from the edges.
|
/// Trim the image removing the backround color from the edges.
|
||||||
pub fn trim_image(&self, fuzz: f64) -> Result<(), &'static str> {
|
pub fn trim_image(&self, fuzz: f64) -> Result<(), &'static str> {
|
||||||
let result = unsafe {
|
let result = unsafe { bindings::MagickTrimImage(self.wand, fuzz) };
|
||||||
bindings::MagickTrimImage(self.wand, fuzz)
|
|
||||||
};
|
|
||||||
match result {
|
match result {
|
||||||
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
||||||
_ => Err("failed to trim image")
|
_ => Err("failed to trim image"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve the width of the image.
|
/// Retrieve the width of the image.
|
||||||
pub fn get_image_width(&self) -> usize {
|
pub fn get_image_width(&self) -> usize {
|
||||||
unsafe {
|
unsafe { bindings::MagickGetImageWidth(self.wand) as usize }
|
||||||
bindings::MagickGetImageWidth(self.wand) as usize
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve the height of the image.
|
/// Retrieve the height of the image.
|
||||||
pub fn get_image_height(&self) -> usize {
|
pub fn get_image_height(&self) -> usize {
|
||||||
unsafe {
|
unsafe { bindings::MagickGetImageHeight(self.wand) as usize }
|
||||||
bindings::MagickGetImageHeight(self.wand) as usize
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve the page geometry (width, height, x offset, y offset) of the image.
|
/// Retrieve the page geometry (width, height, x offset, y offset) of the image.
|
||||||
@ -297,9 +334,7 @@ impl MagickWand {
|
|||||||
/// Reset the Wand page canvas and position.
|
/// Reset the Wand page canvas and position.
|
||||||
pub fn reset_image_page(&self, page_geometry: &str) -> Result<(), &'static str> {
|
pub fn reset_image_page(&self, page_geometry: &str) -> Result<(), &'static str> {
|
||||||
let c_page_geometry = CString::new(page_geometry).unwrap();
|
let c_page_geometry = CString::new(page_geometry).unwrap();
|
||||||
let result = unsafe {
|
let result = unsafe { bindings::MagickResetImagePage(self.wand, c_page_geometry.as_ptr()) };
|
||||||
bindings::MagickResetImagePage(self.wand, c_page_geometry.as_ptr())
|
|
||||||
};
|
|
||||||
if result == bindings::MagickBooleanType_MagickTrue {
|
if result == bindings::MagickBooleanType_MagickTrue {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
@ -310,9 +345,7 @@ impl MagickWand {
|
|||||||
/// Retrieve the named image property value.
|
/// Retrieve the named image property value.
|
||||||
pub fn get_image_property(&self, name: &str) -> Result<String, &'static str> {
|
pub fn get_image_property(&self, name: &str) -> Result<String, &'static str> {
|
||||||
let c_name = CString::new(name).unwrap();
|
let c_name = CString::new(name).unwrap();
|
||||||
let result = unsafe {
|
let result = unsafe { bindings::MagickGetImageProperty(self.wand, c_name.as_ptr()) };
|
||||||
bindings::MagickGetImageProperty(self.wand, c_name.as_ptr())
|
|
||||||
};
|
|
||||||
let value = if result.is_null() {
|
let value = if result.is_null() {
|
||||||
Err("missing property")
|
Err("missing property")
|
||||||
} else {
|
} else {
|
||||||
@ -345,7 +378,9 @@ impl MagickWand {
|
|||||||
let pw = PixelWand::new();
|
let pw = PixelWand::new();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
if bindings::MagickGetImagePixelColor(self.wand, x, y, pw.wand) == bindings::MagickBooleanType_MagickTrue {
|
if bindings::MagickGetImagePixelColor(self.wand, x, y, pw.wand)
|
||||||
|
== bindings::MagickBooleanType_MagickTrue
|
||||||
|
{
|
||||||
Some(pw)
|
Some(pw)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -357,9 +392,15 @@ impl MagickWand {
|
|||||||
///
|
///
|
||||||
/// samplingFactors: An array of floats representing the sampling factor for each color component (in RGB order).
|
/// samplingFactors: An array of floats representing the sampling factor for each color component (in RGB order).
|
||||||
pub fn set_sampling_factors(&self, samplingFactors: &[f64]) -> Result<(), &'static str> {
|
pub fn set_sampling_factors(&self, samplingFactors: &[f64]) -> Result<(), &'static str> {
|
||||||
match unsafe { bindings::MagickSetSamplingFactors(self.wand, samplingFactors.len(), &samplingFactors[0]) } {
|
match unsafe {
|
||||||
|
bindings::MagickSetSamplingFactors(
|
||||||
|
self.wand,
|
||||||
|
samplingFactors.len(),
|
||||||
|
&samplingFactors[0],
|
||||||
|
)
|
||||||
|
} {
|
||||||
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
||||||
_ => Err("SetSamplingFactors returned false")
|
_ => Err("SetSamplingFactors returned false"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,9 +411,12 @@ impl MagickWand {
|
|||||||
unsafe {
|
unsafe {
|
||||||
bindings::MagickGetImageHistogram(self.wand, &mut color_count)
|
bindings::MagickGetImageHistogram(self.wand, &mut color_count)
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.map(|ptrs| slice::from_raw_parts(ptrs, color_count)
|
.map(|ptrs| {
|
||||||
.iter().map(|raw_wand| PixelWand { wand: *raw_wand })
|
slice::from_raw_parts(ptrs, color_count)
|
||||||
.collect())
|
.iter()
|
||||||
|
.map(|raw_wand| PixelWand { wand: *raw_wand })
|
||||||
|
.collect()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,25 +431,19 @@ impl MagickWand {
|
|||||||
///
|
///
|
||||||
pub fn sharpen_image(&self, radius: f64, sigma: f64) -> Result<(), &'static str> {
|
pub fn sharpen_image(&self, radius: f64, sigma: f64) -> Result<(), &'static str> {
|
||||||
match unsafe { bindings::MagickSharpenImage(self.wand, radius, sigma) } {
|
match unsafe { bindings::MagickSharpenImage(self.wand, radius, sigma) } {
|
||||||
|
|
||||||
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
||||||
|
|
||||||
_ => Err("SharpenImage returned false")
|
_ => Err("SharpenImage returned false"),
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the image background color.
|
/// Set the image background color.
|
||||||
pub fn set_image_background_color(&self, pixel_wand: &PixelWand) -> Result<(), &'static str> {
|
pub fn set_image_background_color(&self, pixel_wand: &PixelWand) -> Result<(), &'static str> {
|
||||||
|
|
||||||
match unsafe { bindings::MagickSetImageBackgroundColor(self.wand, pixel_wand.wand) } {
|
match unsafe { bindings::MagickSetImageBackgroundColor(self.wand, pixel_wand.wand) } {
|
||||||
|
|
||||||
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
||||||
|
|
||||||
_ => Err("SetImageBackgroundColor returned false")
|
_ => Err("SetImageBackgroundColor returned false"),
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the image resolution as a pair (horizontal resolution, vertical resolution)
|
/// Returns the image resolution as a pair (horizontal resolution, vertical resolution)
|
||||||
@ -413,7 +451,9 @@ impl MagickWand {
|
|||||||
let mut x_resolution = 0f64;
|
let mut x_resolution = 0f64;
|
||||||
let mut y_resolution = 0f64;
|
let mut y_resolution = 0f64;
|
||||||
unsafe {
|
unsafe {
|
||||||
if bindings::MagickGetImageResolution(self.wand, &mut x_resolution, &mut y_resolution) == bindings::MagickBooleanType_MagickTrue {
|
if bindings::MagickGetImageResolution(self.wand, &mut x_resolution, &mut y_resolution)
|
||||||
|
== bindings::MagickBooleanType_MagickTrue
|
||||||
|
{
|
||||||
Ok((x_resolution, y_resolution))
|
Ok((x_resolution, y_resolution))
|
||||||
} else {
|
} else {
|
||||||
Err("GetImageResolution returned false")
|
Err("GetImageResolution returned false")
|
||||||
@ -422,9 +462,15 @@ impl MagickWand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the image resolution
|
/// Sets the image resolution
|
||||||
pub fn set_image_resolution(&self, x_resolution: f64, y_resolution: f64) -> Result<(), &'static str> {
|
pub fn set_image_resolution(
|
||||||
|
&self,
|
||||||
|
x_resolution: f64,
|
||||||
|
y_resolution: f64,
|
||||||
|
) -> Result<(), &'static str> {
|
||||||
unsafe {
|
unsafe {
|
||||||
if bindings::MagickSetImageResolution(self.wand, x_resolution, y_resolution) == bindings::MagickBooleanType_MagickTrue {
|
if bindings::MagickSetImageResolution(self.wand, x_resolution, y_resolution)
|
||||||
|
== bindings::MagickBooleanType_MagickTrue
|
||||||
|
{
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err("SetImageResolution returned false")
|
Err("SetImageResolution returned false")
|
||||||
@ -435,7 +481,9 @@ impl MagickWand {
|
|||||||
/// Sets the wand resolution
|
/// Sets the wand resolution
|
||||||
pub fn set_resolution(&self, x_resolution: f64, y_resolution: f64) -> Result<(), &'static str> {
|
pub fn set_resolution(&self, x_resolution: f64, y_resolution: f64) -> Result<(), &'static str> {
|
||||||
unsafe {
|
unsafe {
|
||||||
if bindings::MagickSetResolution(self.wand, x_resolution, y_resolution) == bindings::MagickBooleanType_MagickTrue {
|
if bindings::MagickSetResolution(self.wand, x_resolution, y_resolution)
|
||||||
|
== bindings::MagickBooleanType_MagickTrue
|
||||||
|
{
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err("SetResolution returned false")
|
Err("SetResolution returned false")
|
||||||
@ -446,7 +494,9 @@ impl MagickWand {
|
|||||||
/// Returns the image resolution as a pair (horizontal resolution, vertical resolution)
|
/// Returns the image resolution as a pair (horizontal resolution, vertical resolution)
|
||||||
pub fn sepia_tone_image(&self, threshold: f64) -> Result<(), &'static str> {
|
pub fn sepia_tone_image(&self, threshold: f64) -> Result<(), &'static str> {
|
||||||
unsafe {
|
unsafe {
|
||||||
if bindings::MagickSepiaToneImage(self.wand, threshold * bindings::QuantumRange) == bindings::MagickBooleanType_MagickTrue {
|
if bindings::MagickSepiaToneImage(self.wand, threshold * bindings::QuantumRange)
|
||||||
|
== bindings::MagickBooleanType_MagickTrue
|
||||||
|
{
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err("SepiaToneImage returned false")
|
Err("SepiaToneImage returned false")
|
||||||
@ -456,15 +506,31 @@ impl MagickWand {
|
|||||||
|
|
||||||
/// Extracts pixel data from the image as a vector of 0..255 values defined by `map`.
|
/// Extracts pixel data from the image as a vector of 0..255 values defined by `map`.
|
||||||
/// See https://www.imagemagick.org/api/magick-image.php#MagickExportImagePixels for more information.
|
/// See https://www.imagemagick.org/api/magick-image.php#MagickExportImagePixels for more information.
|
||||||
pub fn export_image_pixels(&self, x: isize, y: isize, width: usize, height: usize, map: &str) -> Option<Vec<u8>> {
|
pub fn export_image_pixels(
|
||||||
|
&self,
|
||||||
|
x: isize,
|
||||||
|
y: isize,
|
||||||
|
width: usize,
|
||||||
|
height: usize,
|
||||||
|
map: &str,
|
||||||
|
) -> Option<Vec<u8>> {
|
||||||
let c_map = CString::new(map).unwrap();
|
let c_map = CString::new(map).unwrap();
|
||||||
let capacity = width * height * map.len();
|
let capacity = width * height * map.len();
|
||||||
let mut pixels = Vec::with_capacity(capacity);
|
let mut pixels = Vec::with_capacity(capacity);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
pixels.set_len(capacity as usize);
|
pixels.set_len(capacity as usize);
|
||||||
if bindings::MagickExportImagePixels(self.wand, x, y, width, height, c_map.as_ptr(),
|
if bindings::MagickExportImagePixels(
|
||||||
bindings::StorageType_CharPixel, pixels.as_mut_ptr() as *mut c_void) == bindings::MagickBooleanType_MagickTrue {
|
self.wand,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
c_map.as_ptr(),
|
||||||
|
bindings::StorageType_CharPixel,
|
||||||
|
pixels.as_mut_ptr() as *mut c_void,
|
||||||
|
) == bindings::MagickBooleanType_MagickTrue
|
||||||
|
{
|
||||||
Some(pixels)
|
Some(pixels)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -474,35 +540,38 @@ impl MagickWand {
|
|||||||
|
|
||||||
/// Resize the image to the specified width and height, using the
|
/// Resize the image to the specified width and height, using the
|
||||||
/// specified filter type.
|
/// specified filter type.
|
||||||
pub fn resize_image(&self, width: usize, height: usize,
|
pub fn resize_image(&self, width: usize, height: usize, filter: bindings::FilterType) {
|
||||||
filter: bindings::FilterType) {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
bindings::MagickResizeImage(
|
bindings::MagickResizeImage(self.wand, width as size_t, height as size_t, filter);
|
||||||
self.wand, width as size_t, height as size_t, filter
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extract a region of the image. The width and height is used as the size
|
/// Extract a region of the image. The width and height is used as the size
|
||||||
/// of the region. X and Y is the offset.
|
/// of the region. X and Y is the offset.
|
||||||
pub fn crop_image(&self, width: usize, height: usize, x: isize, y: isize) -> Result<(), &'static str> {
|
pub fn crop_image(
|
||||||
let result = unsafe {
|
&self,
|
||||||
bindings::MagickCropImage(self.wand, width, height, x, y)
|
width: usize,
|
||||||
};
|
height: usize,
|
||||||
|
x: isize,
|
||||||
|
y: isize,
|
||||||
|
) -> Result<(), &'static str> {
|
||||||
|
let result = unsafe { bindings::MagickCropImage(self.wand, width, height, x, y) };
|
||||||
match result {
|
match result {
|
||||||
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
||||||
_ => Err("failed to crop image")
|
_ => Err("failed to crop image"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resample the image to the specified horizontal and vertical resolution, using the
|
/// Resample the image to the specified horizontal and vertical resolution, using the
|
||||||
/// specified filter type.
|
/// specified filter type.
|
||||||
pub fn resample_image(&self, x_resolution: f64, y_resolution: f64,
|
pub fn resample_image(
|
||||||
filter: bindings::FilterType) {
|
&self,
|
||||||
|
x_resolution: f64,
|
||||||
|
y_resolution: f64,
|
||||||
|
filter: bindings::FilterType,
|
||||||
|
) {
|
||||||
unsafe {
|
unsafe {
|
||||||
bindings::MagickResampleImage(
|
bindings::MagickResampleImage(self.wand, x_resolution, y_resolution, filter);
|
||||||
self.wand, x_resolution, y_resolution, filter
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -525,8 +594,12 @@ impl MagickWand {
|
|||||||
unsafe {
|
unsafe {
|
||||||
bindings::MagickResetIterator(self.wand);
|
bindings::MagickResetIterator(self.wand);
|
||||||
while bindings::MagickNextImage(self.wand) != bindings::MagickBooleanType_MagickFalse {
|
while bindings::MagickNextImage(self.wand) != bindings::MagickBooleanType_MagickFalse {
|
||||||
bindings::MagickResizeImage(self.wand, new_width, new_height,
|
bindings::MagickResizeImage(
|
||||||
bindings::FilterType_LanczosFilter);
|
self.wand,
|
||||||
|
new_width,
|
||||||
|
new_height,
|
||||||
|
bindings::FilterType_LanczosFilter,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -535,7 +608,8 @@ impl MagickWand {
|
|||||||
/// hence should be "auto" oriented so it is suitable for viewing.
|
/// hence should be "auto" oriented so it is suitable for viewing.
|
||||||
pub fn requires_orientation(&self) -> bool {
|
pub fn requires_orientation(&self) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
bindings::MagickGetImageOrientation(self.wand) != bindings::OrientationType_TopLeftOrientation
|
bindings::MagickGetImageOrientation(self.wand)
|
||||||
|
!= bindings::OrientationType_TopLeftOrientation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -552,12 +626,10 @@ impl MagickWand {
|
|||||||
/// Write the current image to the provided path.
|
/// Write the current image to the provided path.
|
||||||
pub fn write_image(&self, path: &str) -> Result<(), &'static str> {
|
pub fn write_image(&self, path: &str) -> Result<(), &'static str> {
|
||||||
let c_name = CString::new(path).unwrap();
|
let c_name = CString::new(path).unwrap();
|
||||||
let result = unsafe {
|
let result = unsafe { bindings::MagickWriteImage(self.wand, c_name.as_ptr()) };
|
||||||
bindings::MagickWriteImage(self.wand, c_name.as_ptr())
|
|
||||||
};
|
|
||||||
match result {
|
match result {
|
||||||
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
||||||
_ => Err("failed to write image")
|
_ => Err("failed to write image"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -627,9 +699,7 @@ impl MagickWand {
|
|||||||
MagickUniqueImageColors => unique_image_colors()
|
MagickUniqueImageColors => unique_image_colors()
|
||||||
);
|
);
|
||||||
|
|
||||||
get!(
|
get!(get_image_colors, MagickGetImageColors, size_t);
|
||||||
get_image_colors, MagickGetImageColors, size_t
|
|
||||||
);
|
|
||||||
|
|
||||||
string_set_get!(
|
string_set_get!(
|
||||||
get_filename, set_filename, MagickGetFilename, MagickSetFilename
|
get_filename, set_filename, MagickGetFilename, MagickSetFilename
|
||||||
@ -670,7 +740,6 @@ impl MagickWand {
|
|||||||
get_pointsize, set_pointsize, MagickGetPointsize, MagickSetPointsize, f64
|
get_pointsize, set_pointsize, MagickGetPointsize, MagickSetPointsize, f64
|
||||||
get_type, set_type, MagickGetType, MagickSetType, bindings::ImageType
|
get_type, set_type, MagickGetType, MagickSetType, bindings::ImageType
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for MagickWand {
|
impl fmt::Debug for MagickWand {
|
||||||
|
|||||||
@ -13,11 +13,12 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
#[macro_use] mod macros;
|
#[macro_use]
|
||||||
mod magick;
|
mod macros;
|
||||||
mod drawing;
|
mod drawing;
|
||||||
|
mod magick;
|
||||||
mod pixel;
|
mod pixel;
|
||||||
|
|
||||||
pub use self::magick::MagickWand;
|
|
||||||
pub use self::drawing::DrawingWand;
|
pub use self::drawing::DrawingWand;
|
||||||
pub use self::pixel::{HSL, PixelWand};
|
pub use self::magick::MagickWand;
|
||||||
|
pub use self::pixel::{PixelWand, HSL};
|
||||||
|
|||||||
@ -13,53 +13,58 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
use std::fmt;
|
use bindings;
|
||||||
use std::ffi::{CStr, CString};
|
|
||||||
use ::bindings;
|
|
||||||
#[cfg(target_os = "freebsd")]
|
#[cfg(target_os = "freebsd")]
|
||||||
use libc::size_t;
|
use libc::size_t;
|
||||||
#[cfg(not(target_os = "freebsd"))]
|
#[cfg(not(target_os = "freebsd"))]
|
||||||
use ::size_t;
|
use size_t;
|
||||||
|
use std::ffi::{CStr, CString};
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
pub struct HSL {
|
pub struct HSL {
|
||||||
pub hue: f64,
|
pub hue: f64,
|
||||||
pub saturation: f64,
|
pub saturation: f64,
|
||||||
pub lightness: f64
|
pub lightness: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
wand_common!(
|
wand_common!(
|
||||||
PixelWand,
|
PixelWand,
|
||||||
NewPixelWand, ClearPixelWand, IsPixelWand, ClonePixelWand, DestroyPixelWand,
|
NewPixelWand,
|
||||||
PixelClearException, PixelGetExceptionType, PixelGetException
|
ClearPixelWand,
|
||||||
|
IsPixelWand,
|
||||||
|
ClonePixelWand,
|
||||||
|
DestroyPixelWand,
|
||||||
|
PixelClearException,
|
||||||
|
PixelGetExceptionType,
|
||||||
|
PixelGetException
|
||||||
);
|
);
|
||||||
|
|
||||||
impl PixelWand {
|
impl PixelWand {
|
||||||
pub fn is_similar(&self, other: &PixelWand, fuzz: f64) -> Result<(), &'static str> {
|
pub fn is_similar(&self, other: &PixelWand, fuzz: f64) -> Result<(), &'static str> {
|
||||||
match unsafe { bindings::IsPixelWandSimilar(self.wand, other.wand, fuzz) } {
|
match unsafe { bindings::IsPixelWandSimilar(self.wand, other.wand, fuzz) } {
|
||||||
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
||||||
_ => Err("not similar")
|
_ => Err("not similar"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_hsl(&self) -> HSL {
|
pub fn get_hsl(&self) -> HSL {
|
||||||
let mut hsl = HSL::default();
|
let mut hsl = HSL::default();
|
||||||
unsafe { bindings::PixelGetHSL(
|
unsafe {
|
||||||
|
bindings::PixelGetHSL(
|
||||||
self.wand,
|
self.wand,
|
||||||
&mut hsl.hue as *mut _,
|
&mut hsl.hue as *mut _,
|
||||||
&mut hsl.saturation as *mut _,
|
&mut hsl.saturation as *mut _,
|
||||||
&mut hsl.lightness as *mut _
|
&mut hsl.lightness as *mut _,
|
||||||
);}
|
);
|
||||||
|
}
|
||||||
hsl
|
hsl
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_hsl(&self, hsl: &HSL) {
|
pub fn set_hsl(&self, hsl: &HSL) {
|
||||||
unsafe { bindings::PixelSetHSL(
|
unsafe {
|
||||||
self.wand,
|
bindings::PixelSetHSL(self.wand, hsl.hue, hsl.saturation, hsl.lightness);
|
||||||
hsl.hue,
|
}
|
||||||
hsl.saturation,
|
|
||||||
hsl.lightness
|
|
||||||
);}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmt_w_prefix(&self, f: &mut fmt::Formatter, prefix: &str) -> fmt::Result {
|
pub fn fmt_w_prefix(&self, f: &mut fmt::Formatter, prefix: &str) -> fmt::Result {
|
||||||
@ -75,14 +80,17 @@ impl PixelWand {
|
|||||||
|
|
||||||
pub fn set_color(&mut self, s: &str) -> Result<(), &'static str> {
|
pub fn set_color(&mut self, s: &str) -> Result<(), &'static str> {
|
||||||
let c_string = try!(CString::new(s).map_err(|_| "could not convert to cstring"));
|
let c_string = try!(CString::new(s).map_err(|_| "could not convert to cstring"));
|
||||||
match unsafe { bindings::PixelSetColor(self.wand, c_string.as_ptr())} {
|
match unsafe { bindings::PixelSetColor(self.wand, c_string.as_ptr()) } {
|
||||||
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
bindings::MagickBooleanType_MagickTrue => Ok(()),
|
||||||
_ => Err("failed to set color")
|
_ => Err("failed to set color"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string_get!(get_color_as_string, PixelGetColorAsString);
|
string_get!(get_color_as_string, PixelGetColorAsString);
|
||||||
string_get!(get_color_as_normalized_string, PixelGetColorAsNormalizedString);
|
string_get!(
|
||||||
|
get_color_as_normalized_string,
|
||||||
|
PixelGetColorAsNormalizedString
|
||||||
|
);
|
||||||
|
|
||||||
set_get_unchecked!(
|
set_get_unchecked!(
|
||||||
get_color_count, set_color_count, PixelGetColorCount, PixelSetColorCount, size_t
|
get_color_count, set_color_count, PixelGetColorCount, PixelSetColorCount, size_t
|
||||||
|
|||||||
57
tests/lib.rs
57
tests/lib.rs
@ -16,14 +16,14 @@
|
|||||||
|
|
||||||
extern crate magick_rust;
|
extern crate magick_rust;
|
||||||
|
|
||||||
use magick_rust::{MagickWand, magick_wand_genesis, PixelWand, bindings};
|
use magick_rust::{bindings, magick_wand_genesis, MagickWand, PixelWand};
|
||||||
|
|
||||||
|
use magick_rust::ToMagick;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::{Once, ONCE_INIT};
|
use std::sync::{Once, ONCE_INIT};
|
||||||
use magick_rust::ToMagick;
|
|
||||||
|
|
||||||
// Used to make sure MagickWand is initialized exactly once. Note that we
|
// Used to make sure MagickWand is initialized exactly once. Note that we
|
||||||
// do not bother shutting down, we simply exit when the tests are done.
|
// do not bother shutting down, we simply exit when the tests are done.
|
||||||
@ -48,11 +48,11 @@ fn test_resize_image() {
|
|||||||
assert_eq!(384, wand.get_image_height());
|
assert_eq!(384, wand.get_image_height());
|
||||||
let halfwidth = match wand.get_image_width() {
|
let halfwidth = match wand.get_image_width() {
|
||||||
1 => 1,
|
1 => 1,
|
||||||
width => width / 2
|
width => width / 2,
|
||||||
};
|
};
|
||||||
let halfheight = match wand.get_image_height() {
|
let halfheight = match wand.get_image_height() {
|
||||||
1 => 1,
|
1 => 1,
|
||||||
height => height / 2
|
height => height / 2,
|
||||||
};
|
};
|
||||||
wand.resize_image(halfwidth, halfheight, bindings::FilterType_LanczosFilter);
|
wand.resize_image(halfwidth, halfheight, bindings::FilterType_LanczosFilter);
|
||||||
assert_eq!(256, wand.get_image_width());
|
assert_eq!(256, wand.get_image_width());
|
||||||
@ -69,12 +69,12 @@ fn test_read_from_blob() {
|
|||||||
let path = Path::new("tests/data/IMG_5745.JPG");
|
let path = Path::new("tests/data/IMG_5745.JPG");
|
||||||
let mut file = match File::open(&path) {
|
let mut file = match File::open(&path) {
|
||||||
Err(why) => panic!("couldn't open file: {}", Error::description(&why)),
|
Err(why) => panic!("couldn't open file: {}", Error::description(&why)),
|
||||||
Ok(file) => file
|
Ok(file) => file,
|
||||||
};
|
};
|
||||||
let mut data: Vec<u8> = Vec::new();
|
let mut data: Vec<u8> = Vec::new();
|
||||||
match file.read_to_end(&mut data) {
|
match file.read_to_end(&mut data) {
|
||||||
Err(why) => panic!("couldn't read file: {}", Error::description(&why)),
|
Err(why) => panic!("couldn't read file: {}", Error::description(&why)),
|
||||||
Ok(_) => ()
|
Ok(_) => (),
|
||||||
};
|
};
|
||||||
assert!(wand.read_image_blob(&data).is_ok());
|
assert!(wand.read_image_blob(&data).is_ok());
|
||||||
assert_eq!(512, wand.get_image_width());
|
assert_eq!(512, wand.get_image_width());
|
||||||
@ -186,7 +186,8 @@ fn test_compare_images() {
|
|||||||
assert!(wand2.read_image("tests/data/IMG_5745_rotl.JPG").is_ok());
|
assert!(wand2.read_image("tests/data/IMG_5745_rotl.JPG").is_ok());
|
||||||
wand2.auto_orient();
|
wand2.auto_orient();
|
||||||
|
|
||||||
let (distortion, diff) = wand1.compare_images(&wand2, bindings::MetricType_RootMeanSquaredErrorMetric);
|
let (distortion, diff) =
|
||||||
|
wand1.compare_images(&wand2, bindings::MetricType_RootMeanSquaredErrorMetric);
|
||||||
assert!(distortion < 0.01);
|
assert!(distortion < 0.01);
|
||||||
assert!(diff.is_some());
|
assert!(diff.is_some());
|
||||||
}
|
}
|
||||||
@ -225,21 +226,32 @@ fn test_transform_image_colorspace() {
|
|||||||
});
|
});
|
||||||
let wand = MagickWand::new();
|
let wand = MagickWand::new();
|
||||||
assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok());
|
assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok());
|
||||||
assert_eq!(wand.get_image_colorspace(), bindings::ColorspaceType_sRGBColorspace);
|
assert_eq!(
|
||||||
|
wand.get_image_colorspace(),
|
||||||
|
bindings::ColorspaceType_sRGBColorspace
|
||||||
|
);
|
||||||
|
|
||||||
let pixel_color = wand.get_image_pixel_color(10, 10).unwrap();
|
let pixel_color = wand.get_image_pixel_color(10, 10).unwrap();
|
||||||
assert_ne!(pixel_color.get_hsl().hue, 0.0);
|
assert_ne!(pixel_color.get_hsl().hue, 0.0);
|
||||||
|
|
||||||
assert!(wand.transform_image_colorspace(bindings::ColorspaceType_GRAYColorspace).is_ok());
|
assert!(
|
||||||
assert_eq!(wand.get_image_colorspace(), bindings::ColorspaceType_GRAYColorspace);
|
wand.transform_image_colorspace(bindings::ColorspaceType_GRAYColorspace)
|
||||||
|
.is_ok()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
wand.get_image_colorspace(),
|
||||||
|
bindings::ColorspaceType_GRAYColorspace
|
||||||
|
);
|
||||||
|
|
||||||
let pixel_grayscale = wand.get_image_pixel_color(10, 10).unwrap();
|
let pixel_grayscale = wand.get_image_pixel_color(10, 10).unwrap();
|
||||||
assert_eq!(pixel_grayscale.get_hsl().hue, 0.0);
|
assert_eq!(pixel_grayscale.get_hsl().hue, 0.0);
|
||||||
|
|
||||||
/* The output of `export_image_pixels` should match
|
/* The output of `export_image_pixels` should match
|
||||||
* `convert -type Grayscale tests/data/IMG_5745.JPG[2x2+0+0] txt:` */
|
* `convert -type Grayscale tests/data/IMG_5745.JPG[2x2+0+0] txt:` */
|
||||||
assert_eq!(wand.export_image_pixels(0, 0, 2, 2, "I").unwrap(),
|
assert_eq!(
|
||||||
vec![212, 212, 210, 210])
|
wand.export_image_pixels(0, 0, 2, 2, "I").unwrap(),
|
||||||
|
vec![212, 212, 210, 210]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -254,14 +266,24 @@ fn test_color_reduction() {
|
|||||||
let image_colors = wand.get_image_colors();
|
let image_colors = wand.get_image_colors();
|
||||||
assert!(image_colors > 38000 || image_colors < 40000);
|
assert!(image_colors > 38000 || image_colors < 40000);
|
||||||
|
|
||||||
assert!(wand.quantize_image(6, bindings::ColorspaceType_RGBColorspace, 1,
|
assert!(
|
||||||
bindings::DitherMethod_UndefinedDitherMethod, false.to_magick()).is_ok());
|
wand.quantize_image(
|
||||||
|
6,
|
||||||
|
bindings::ColorspaceType_RGBColorspace,
|
||||||
|
1,
|
||||||
|
bindings::DitherMethod_UndefinedDitherMethod,
|
||||||
|
false.to_magick()
|
||||||
|
).is_ok()
|
||||||
|
);
|
||||||
assert_eq!(6, wand.get_image_colors());
|
assert_eq!(6, wand.get_image_colors());
|
||||||
|
|
||||||
let histogram = wand.get_image_histogram().unwrap();
|
let histogram = wand.get_image_histogram().unwrap();
|
||||||
assert_eq!(6, histogram.len());
|
assert_eq!(6, histogram.len());
|
||||||
assert_eq!(wand.get_image_width() * wand.get_image_height(),
|
assert_eq!(
|
||||||
histogram.iter().fold(0, |total_colors, wand| total_colors + wand.get_color_count()));
|
wand.get_image_width() * wand.get_image_height(),
|
||||||
|
histogram.iter().fold(0, |total_colors, wand| total_colors
|
||||||
|
+ wand.get_color_count())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -274,7 +296,8 @@ fn test_set_image_background_color() {
|
|||||||
let mut pw = PixelWand::new();
|
let mut pw = PixelWand::new();
|
||||||
pw.set_color("#0000FF").unwrap();
|
pw.set_color("#0000FF").unwrap();
|
||||||
wand.set_image_background_color(&pw).unwrap();
|
wand.set_image_background_color(&pw).unwrap();
|
||||||
wand.set_image_alpha_channel(bindings::AlphaChannelOption_RemoveAlphaChannel).unwrap();
|
wand.set_image_alpha_channel(bindings::AlphaChannelOption_RemoveAlphaChannel)
|
||||||
|
.unwrap();
|
||||||
let blob = wand.write_image_blob("rgb").unwrap();
|
let blob = wand.write_image_blob("rgb").unwrap();
|
||||||
assert_eq!(0u8, blob[0]);
|
assert_eq!(0u8, blob[0]);
|
||||||
assert_eq!(0u8, blob[1]);
|
assert_eq!(0u8, blob[1]);
|
||||||
|
|||||||
Reference in New Issue
Block a user