From 4dda874de11149d1d26e7556bc776ec4df32af9b Mon Sep 17 00:00:00 2001 From: asonix Date: Sat, 10 Oct 2020 17:42:35 -0500 Subject: [PATCH 01/10] Add sample method --- src/wand/magick.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/wand/magick.rs b/src/wand/magick.rs index 153f4f3..a94d991 100644 --- a/src/wand/magick.rs +++ b/src/wand/magick.rs @@ -677,6 +677,18 @@ impl MagickWand { } } + /// Sample the image to the target resolution + /// + /// This is incredibly fast, as it does 1-1 pixel mapping for downscales, and box filtering for + /// upscales + pub fn sample_image(&self, width: usize, height: usize) -> Result<(), &'static str> { + let result = unsafe { bindings::MagickSampleImage(self.wand, width, height) }; + match result { + bindings::MagickBooleanType_MagickTrue => Ok(()), + _ => Err("failed to sample image"), + } + } + /// Resample the image to the specified horizontal and vertical resolution, using the /// specified filter type. pub fn resample_image( From e387f40bf0673f22bc8fac151e8341b211071930 Mon Sep 17 00:00:00 2001 From: asonix Date: Sat, 10 Oct 2020 17:46:38 -0500 Subject: [PATCH 02/10] Add quantum depth --- build.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build.rs b/build.rs index 65115f3..0225356 100644 --- a/build.rs +++ b/build.rs @@ -26,7 +26,9 @@ use std::process::Command; const MIN_VERSION: &'static str = "7.0"; const MAX_VERSION: &'static str = "7.1"; -static HEADER: &'static str = "#include \n"; +static HEADER: &'static str = r#"#define MAGICKCORE_QUANTUM_DEPTH 8 +#include +"#; fn main() { if cfg!(target_os = "freebsd") { From d82484e7dec544bfb4ae49bba9778f064165831a Mon Sep 17 00:00:00 2001 From: asonix Date: Sun, 11 Oct 2020 13:18:19 -0500 Subject: [PATCH 03/10] Set environment variable with magickcore config flags --- build.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/build.rs b/build.rs index 0225356..9dce66c 100644 --- a/build.rs +++ b/build.rs @@ -26,9 +26,7 @@ use std::process::Command; const MIN_VERSION: &'static str = "7.0"; const MAX_VERSION: &'static str = "7.1"; -static HEADER: &'static str = r#"#define MAGICKCORE_QUANTUM_DEPTH 8 -#include -"#; +static HEADER: &'static str = "#include \n"; fn main() { if cfg!(target_os = "freebsd") { @@ -43,6 +41,15 @@ fn main() { env_var_set_default("IMAGE_MAGICK_LIBS", "MagickWand-7"); } + let cppflags = Command::new("MagickCore-config") + .arg("--cppflags") + .output() + .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() { From 65903434cd9ed9020045ae36caf841a2210315a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20R=C3=B6nnkvist?= Date: Fri, 16 Oct 2020 15:57:57 +0200 Subject: [PATCH 04/10] feat: modulate image --- src/wand/magick.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/wand/magick.rs b/src/wand/magick.rs index a94d991..a1b7034 100644 --- a/src/wand/magick.rs +++ b/src/wand/magick.rs @@ -830,6 +830,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) From 9f70ef94fa57fcbdb51a785bf8b565ef2ae3d68a Mon Sep 17 00:00:00 2001 From: Romain Leroux Date: Mon, 21 Dec 2020 01:58:41 +0100 Subject: [PATCH 05/10] Add kmeans --- src/wand/magick.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/wand/magick.rs b/src/wand/magick.rs index a1b7034..0ee0c77 100644 --- a/src/wand/magick.rs +++ b/src/wand/magick.rs @@ -849,6 +849,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); From e8170defca5add2458c27f5cf1eaefe1bb713a43 Mon Sep 17 00:00:00 2001 From: fabio h Date: Sat, 23 Jan 2021 10:23:00 -0300 Subject: [PATCH 06/10] Required version bump on bindgen. More info: https://github.com/rust-lang/rust-bindgen/pull/1826. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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] From 82778e69f5c130e5adac019528b72618b198e4cb Mon Sep 17 00:00:00 2001 From: Nathan Fiedler Date: Sat, 23 Jan 2021 09:38:46 -0800 Subject: [PATCH 07/10] chore: fix the ImageMagick URL for docker container build --- docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 \ From 480421aa65ae6b0a1788cd17ae7c1c9a62d3f7aa Mon Sep 17 00:00:00 2001 From: liyunde Date: Thu, 11 Mar 2021 14:25:32 +0800 Subject: [PATCH 08/10] fix path_separator on windows can not build --- build.rs | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/build.rs b/build.rs index 9dce66c..e4a7968 100644 --- a/build.rs +++ b/build.rs @@ -28,6 +28,12 @@ const MAX_VERSION: &'static str = "7.1"; static HEADER: &'static str = "#include \n"; +//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 @@ -41,14 +47,14 @@ fn main() { env_var_set_default("IMAGE_MAGICK_LIBS", "MagickWand-7"); } - let cppflags = Command::new("MagickCore-config") - .arg("--cppflags") - .output() - .unwrap() - .stdout; - let cppflags = String::from_utf8(cppflags).unwrap(); + 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); + env_var_set_default("BINDGEN_EXTRA_CLANG_ARGS", &cppflags); + } let lib_dirs = find_image_magick_lib_dirs(); for d in &lib_dirs { @@ -75,7 +81,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()] @@ -172,7 +178,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") @@ -181,7 +191,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) From 94228253227b06267eb8cef8f0e4b3bf5a46dd73 Mon Sep 17 00:00:00 2001 From: Nathan Fiedler Date: Sat, 27 Mar 2021 11:22:50 -0700 Subject: [PATCH 09/10] fix: in Rust 1.51 panic! takes only string literals Seems that Rust 2021 will require that panic! macro takes only a string literal, so format! and variables are out. cargo test passes --- build.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/build.rs b/build.rs index e4a7968..b9a12a1 100644 --- a/build.rs +++ b/build.rs @@ -272,10 +272,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). From a14b44974d932c8bc03251b77dfd2237838b50b6 Mon Sep 17 00:00:00 2001 From: Gleb Pomykalov Date: Sat, 10 Apr 2021 12:36:40 +0300 Subject: [PATCH 10/10] support resource limits --- src/wand/magick.rs | 30 ++++++++++++++++++++++++++++++ src/wand/mod.rs | 2 +- tests/lib.rs | 12 +++++++++++- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/wand/magick.rs b/src/wand/magick.rs index 0ee0c77..2497d0a 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(); 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()); +}