diff --git a/Cargo.toml b/Cargo.toml index e29e0d9..f8e3b78 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ build = "build.rs" libc = "0.2.70" [build-dependencies] -bindgen = "0.53.2" +bindgen = "0.56.0" pkg-config = "0.3.17" [features] diff --git a/build.rs b/build.rs index 686884e..02a06d1 100644 --- a/build.rs +++ b/build.rs @@ -30,6 +30,12 @@ static HEADER: &'static str = r#"#define MAGICKCORE_QUANTUM_DEPTH 16 #include "#; +//on windows path env always contain : like c: +pub const PATH_SEPARATOR: &str = match cfg!(target_os = "windows") { + true => ";", + _ => ":", +}; + fn main() { if cfg!(target_os = "freebsd") { // pkg_config does not seem to work properly on FreeBSD, so @@ -43,6 +49,15 @@ fn main() { env_var_set_default("IMAGE_MAGICK_LIBS", "MagickWand-7"); } + let check_cppflags = Command::new("MagickCore-config").arg("--cppflags").output(); + //on windows can not exec + if check_cppflags.is_ok() { + let cppflags = check_cppflags.unwrap().stdout; + let cppflags = String::from_utf8(cppflags).unwrap(); + + env_var_set_default("BINDGEN_EXTRA_CLANG_ARGS", &cppflags); + } + let lib_dirs = find_image_magick_lib_dirs(); for d in &lib_dirs { if !d.exists() { @@ -68,7 +83,7 @@ fn main() { let target = env::var("TARGET").unwrap(); let libs_env = env::var("IMAGE_MAGICK_LIBS").ok(); let libs = match libs_env { - Some(ref v) => v.split(":").map(|x| x.to_owned()).collect(), + Some(ref v) => v.split(PATH_SEPARATOR).map(|x| x.to_owned()).collect(), None => { if target.contains("windows") { vec!["CORE_RL_MagickWand_".to_string()] @@ -165,7 +180,11 @@ fn env_var_set_default(name: &str, value: &str) { fn find_image_magick_lib_dirs() -> Vec { println!("cargo:rerun-if-env-changed=IMAGE_MAGICK_LIB_DIRS"); env::var("IMAGE_MAGICK_LIB_DIRS") - .map(|x| x.split(":").map(PathBuf::from).collect::>()) + .map(|x| { + x.split(PATH_SEPARATOR) + .map(PathBuf::from) + .collect::>() + }) .or_else(|_| Ok(vec![find_image_magick_dir()?.join("lib")])) .or_else(|_: env::VarError| -> Result<_, env::VarError> { Ok(run_pkg_config().link_paths) }) .expect("Couldn't find ImageMagick library directory") @@ -174,7 +193,11 @@ fn find_image_magick_lib_dirs() -> Vec { fn find_image_magick_include_dirs() -> Vec { println!("cargo:rerun-if-env-changed=IMAGE_MAGICK_INCLUDE_DIRS"); env::var("IMAGE_MAGICK_INCLUDE_DIRS") - .map(|x| x.split(":").map(PathBuf::from).collect::>()) + .map(|x| { + x.split(PATH_SEPARATOR) + .map(PathBuf::from) + .collect::>() + }) .or_else(|_| Ok(vec![find_image_magick_dir()?.join("include")])) .or_else(|_: env::VarError| -> Result<_, env::VarError> { Ok(run_pkg_config().include_paths) @@ -251,10 +274,7 @@ fn run_pkg_config() -> pkg_config::Library { .unwrap() .success() { - panic!(format!( - "MagickWand version must be no higher than {}", - MAX_VERSION - )); + panic!("MagickWand version must be less than 7.1"); } // 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). diff --git a/docker/Dockerfile b/docker/Dockerfile index 96662b4..5223ae3 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -6,7 +6,7 @@ RUN apt-get update \ ENV MAGICK_VERSION 7.0 -RUN curl https://www.imagemagick.org/download/ImageMagick.tar.gz | tar xz \ +RUN curl https://download.imagemagick.org/ImageMagick/download/ImageMagick.tar.gz | tar xz \ && cd ImageMagick-${MAGICK_VERSION}* \ && ./configure --with-magick-plus-plus=no --with-perl=no \ && make \ diff --git a/src/wand/magick.rs b/src/wand/magick.rs index 767ac70..a60e12b 100644 --- a/src/wand/magick.rs +++ b/src/wand/magick.rs @@ -37,6 +37,23 @@ wand_common!( MagickGetException ); +/// Resource type to use with [set_resource_limit](MagickWand::set_resource_limit) +#[derive(Debug, Clone, Copy)] +pub enum ResourceType { + Undefined = bindings::ResourceType_UndefinedResource as isize, + Area = bindings::ResourceType_AreaResource as isize, + Disk = bindings::ResourceType_DiskResource as isize, + File = bindings::ResourceType_FileResource as isize, + Height = bindings::ResourceType_HeightResource as isize, + Map = bindings::ResourceType_MapResource as isize, + Memory = bindings::ResourceType_MemoryResource as isize, + Thread = bindings::ResourceType_ThreadResource as isize, + Throttle = bindings::ResourceType_ThrottleResource as isize, + Time = bindings::ResourceType_TimeResource as isize, + Width = bindings::ResourceType_WidthResource as isize, + ListLength = bindings::ResourceType_ListLengthResource as isize, +} + /// MagickWand is a Rustic wrapper to the Rust bindings to ImageMagick. /// /// Instantiating a `MagickWand` will construct an ImageMagick "wand" @@ -56,6 +73,19 @@ impl MagickWand { } } + pub fn set_resource_limit(resource: ResourceType, limit: u64) -> Result<(), &'static str> { + let result = unsafe { + bindings::SetMagickResourceLimit( + resource as bindings::ResourceType, + limit as bindings::MagickSizeType, + ) + }; + match result { + bindings::MagickBooleanType_MagickTrue => Ok(()), + _ => Err("failed to set resource limit"), + } + } + pub fn set_option(&mut self, key: &str, value: &str) -> Result<(), &'static str> { let c_key = CString::new(key).unwrap(); let c_value = CString::new(value).unwrap(); @@ -840,6 +870,9 @@ impl MagickWand { // Sets the image to the specified alpha level. MagickSetImageAlpha => set_image_alpha(alpha: f64) + // Control the brightness, saturation, and hue of an image + MagickModulateImage => modulate_image(brightness: f64, saturation: f64, hue: f64) + /// Set the image alpha channel mode. MagickSetImageAlphaChannel => set_image_alpha_channel( alpha_channel: bindings::AlphaChannelOption) @@ -856,6 +889,9 @@ impl MagickWand { /// Discard all but one of any pixel color. MagickUniqueImageColors => unique_image_colors() + + /// Applies k-means color reduction to the image. + MagickKmeansImage => kmeans(number_colors: size_t, max_iterations: size_t, tolerance: f64) ); get!(get_image_colors, MagickGetImageColors, size_t); diff --git a/src/wand/mod.rs b/src/wand/mod.rs index 29601df..2cf9201 100644 --- a/src/wand/mod.rs +++ b/src/wand/mod.rs @@ -20,5 +20,5 @@ mod magick; mod pixel; pub use self::drawing::DrawingWand; -pub use self::magick::MagickWand; +pub use self::magick::{MagickWand, ResourceType}; pub use self::pixel::{PixelWand, HSL}; diff --git a/tests/lib.rs b/tests/lib.rs index 89d31ff..eefbc0a 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -16,7 +16,7 @@ extern crate magick_rust; -use magick_rust::{bindings, magick_wand_genesis, MagickWand, PixelWand}; +use magick_rust::{bindings, magick_wand_genesis, MagickWand, PixelWand, ResourceType}; use magick_rust::ToMagick; use std::error::Error; @@ -361,3 +361,13 @@ fn test_negate_image() { pixel_color.get_color_as_string().unwrap() ); } + +#[test] +fn test_resource_limits() { + START.call_once(|| { + magick_wand_genesis(); + }); + MagickWand::set_resource_limit(ResourceType::Thread, 1).unwrap(); + let wand = MagickWand::new(); + assert!(wand.read_image("tests/data/rust.png").is_ok()); +}