Merge branch 'master' into main

This commit is contained in:
asonix 2021-06-19 14:10:14 -05:00
commit 11da380e1b
9 changed files with 161 additions and 31 deletions

View file

@ -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]

View file

@ -24,9 +24,17 @@ use std::path::{Path, PathBuf};
use std::process::Command;
const MIN_VERSION: &'static str = "7.0";
const MAX_VERSION: &'static str = "7.1";
const MAX_VERSION: &'static str = "7.2";
static HEADER: &'static str = "#include <MagickWand/MagickWand.h>\n";
static HEADER: &'static str = r#"#define MAGICKCORE_QUANTUM_DEPTH 16
#include <MagickWand/MagickWand.h>
"#;
//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") {
@ -41,14 +49,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 +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()]
@ -172,7 +180,11 @@ fn env_var_set_default(name: &str, value: &str) {
fn find_image_magick_lib_dirs() -> Vec<PathBuf> {
println!("cargo:rerun-if-env-changed=IMAGE_MAGICK_LIB_DIRS");
env::var("IMAGE_MAGICK_LIB_DIRS")
.map(|x| x.split(":").map(PathBuf::from).collect::<Vec<PathBuf>>())
.map(|x| {
x.split(PATH_SEPARATOR)
.map(PathBuf::from)
.collect::<Vec<PathBuf>>()
})
.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 +193,11 @@ fn find_image_magick_lib_dirs() -> Vec<PathBuf> {
fn find_image_magick_include_dirs() -> Vec<PathBuf> {
println!("cargo:rerun-if-env-changed=IMAGE_MAGICK_INCLUDE_DIRS");
env::var("IMAGE_MAGICK_INCLUDE_DIRS")
.map(|x| x.split(":").map(PathBuf::from).collect::<Vec<PathBuf>>())
.map(|x| {
x.split(PATH_SEPARATOR)
.map(PathBuf::from)
.collect::<Vec<PathBuf>>()
})
.or_else(|_| Ok(vec![find_image_magick_dir()?.join("include")]))
.or_else(|_: env::VarError| -> Result<_, env::VarError> {
Ok(run_pkg_config().include_paths)
@ -258,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).

View file

@ -4,9 +4,9 @@ RUN apt-get update \
&& apt-get -y install curl build-essential clang pkg-config libjpeg-turbo-progs libpng-dev \
&& rm -rfv /var/lib/apt/lists/*
ENV MAGICK_VERSION 7.0
ENV MAGICK_VERSION 7.1
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 \
@ -16,6 +16,8 @@ RUN curl https://www.imagemagick.org/download/ImageMagick.tar.gz | tar xz \
RUN adduser --disabled-password --gecos '' magick-rust
ADD policy.xml /usr/local/lib/ImageMagick-7.0.11/config-Q16HDRI/policy.xml
USER magick-rust
ENV USER=magick-rust LD_LIBRARY_PATH=/usr/local/lib

34
docker/Dockerfile.docs Normal file
View file

@ -0,0 +1,34 @@
FROM rust:latest as builder
RUN apt-get update \
&& apt-get -y install curl build-essential clang pkg-config libjpeg-turbo-progs libpng-dev \
&& rm -rfv /var/lib/apt/lists/*
ENV MAGICK_VERSION 7.0
RUN curl https://www.imagemagick.org/download/ImageMagick.tar.gz | tar xz \
&& cd ImageMagick-${MAGICK_VERSION}* \
&& ./configure --with-magick-plus-plus=no --with-perl=no \
&& make \
&& make install \
&& cd .. \
&& rm -r ImageMagick-${MAGICK_VERSION}*
RUN adduser --disabled-password --gecos '' magick-rust \
&& mkdir /src \
&& chown magick-rust:magick-rust /src
USER magick-rust
ENV USER=magick-rust LD_LIBRARY_PATH=/usr/local/lib
WORKDIR /src
COPY --chown=magick-rust:magick-rust Cargo.toml Cargo.lock build.rs ./
COPY --chown=magick-rust:magick-rust ./src ./src
RUN cargo doc --no-deps
FROM arm64v8/nginx:mainline-alpine
COPY --from=builder --chown=nginx:nginx /src/target/doc /usr/share/nginx/html

View file

@ -9,3 +9,8 @@ services:
- ..:/src
stdin_open: true
tty: true
magick-docs:
build:
context: ..
dockerfile: docker/Dockerfile.docs

20
docker/policy.xml Normal file
View file

@ -0,0 +1,20 @@
<policymap>
<policy domain="resource" name="memory" value="256MiB" />
<policy domain="resource" name="list-length" value="32" />
<policy domain="resource" name="width" value="10KP" />
<policy domain="resource" name="height" value="10KP" />
<policy domain="resource" name="map" value="512MiB" />
<policy domain="resource" name="area" value="16KP" />
<policy domain="resource" name="disk" value="1GiB" />
<policy domain="resource" name="file" value="768" />
<policy domain="resource" name="thread" value="2" />
<policy domain="coder" rights="none" pattern="*" />
<policy domain="coder" rights="read | write" pattern="{GIF,JPEG,PNG,WEBP}" />
<policy domain="filter" rights="none" pattern="*" />
<policy domain="path" rights="none" pattern="@*" />
<policy domain="delegate" rights="none" pattern="*" />
<policy domain="module" rights="none" pattern="*" />
<policy domain="module" rights="read | write" pattern="{GIF,JPEG,PNG,WEBP}" />
<!-- indirect reads not permitted -->
<policy domain="system" name="precision" value="6" />
</policymap>

View file

@ -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();
@ -267,21 +297,21 @@ impl MagickWand {
// Define two 'quantum_range' functions because the bindings::QuantumRange symbol
// is not available if hdri is disabled in the compiled ImageMagick libs
#[cfg(not(feature="disable-hdri"))]
#[cfg(not(feature = "disable-hdri"))]
fn quantum_range(&self) -> Result<f64, &'static str> {
return Ok(bindings::QuantumRange);
}
// with disable-hdri enabled we define our own quantum_range
// values lifted directly from magick-type.h
#[cfg(feature="disable-hdri")]
#[cfg(feature = "disable-hdri")]
fn quantum_range(&self) -> Result<f64, &'static str> {
match bindings::MAGICKCORE_QUANTUM_DEPTH {
8 => Ok(255.0f64),
16 => Ok(65535.0f64),
32 => Ok(4294967295.0f64),
64 => Ok(18446744073709551615.0f64),
_ => Err("Quantum depth must be one of 8, 16, 32 or 64")
_ => Err("Quantum depth must be one of 8, 16, 32 or 64"),
}
}
@ -309,7 +339,6 @@ impl MagickWand {
}
}
/// 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.
pub fn extend_image(
@ -702,20 +731,31 @@ impl MagickWand {
}
}
/// Rescale the image using seam carving algorithm
pub fn liquid_rescale_image(&self, width: usize, height: usize, delta_x: f64, rigidity: f64) -> Result<(), &'static str> {
match unsafe { bindings::MagickLiquidRescaleImage(self.wand, width, height, delta_x, rigidity) } {
pub fn liquid_rescale_image(
&self,
width: usize,
height: usize,
delta_x: f64,
rigidity: f64,
) -> Result<(), &'static str> {
match unsafe {
bindings::MagickLiquidRescaleImage(self.wand, width, height, delta_x, rigidity)
} {
bindings::MagickBooleanType_MagickTrue => Ok(()),
_ => Err("failed to liquid-rescale image")
_ => Err("failed to liquid-rescale image"),
}
}
/// Implodes the image towards the center by the specified percentage
pub fn implode(&self, amount: f64, method: bindings::PixelInterpolateMethod) -> Result<(), &'static str> {
pub fn implode(
&self,
amount: f64,
method: bindings::PixelInterpolateMethod,
) -> Result<(), &'static str> {
match unsafe { bindings::MagickImplodeImage(self.wand, amount, method) } {
bindings::MagickBooleanType_MagickTrue => Ok(()),
_ => Err("failed to implode image")
_ => Err("failed to implode image"),
}
}
@ -830,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)
@ -846,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);

View file

@ -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};

View file

@ -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());
}