diff --git a/src/lib.rs b/src/lib.rs index cbe2dbf..35bda30 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,7 +36,7 @@ use libc::size_t; #[cfg(not(target_os = "freebsd"))] use libc::ssize_t; -pub use bindings::{ColorspaceType, DitherMethod, FilterType, GravityType}; +pub use bindings::{DitherMethod, FilterType, GravityType}; pub use conversions::ToMagick; pub use result::MagickError; use result::Result; diff --git a/src/types/colorspace_type.rs b/src/types/colorspace_type.rs new file mode 100644 index 0000000..726584b --- /dev/null +++ b/src/types/colorspace_type.rs @@ -0,0 +1,75 @@ +use crate::bindings; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(u32)] +pub enum ColorspaceType { + Undefined = bindings::ColorspaceType_UndefinedColorspace, + CMY = bindings::ColorspaceType_CMYColorspace, + CMYK = bindings::ColorspaceType_CMYKColorspace, + GRAY = bindings::ColorspaceType_GRAYColorspace, + HCL = bindings::ColorspaceType_HCLColorspace, + HCLp = bindings::ColorspaceType_HCLpColorspace, + HSB = bindings::ColorspaceType_HSBColorspace, + HSI = bindings::ColorspaceType_HSIColorspace, + HSL = bindings::ColorspaceType_HSLColorspace, + HSV = bindings::ColorspaceType_HSVColorspace, + HWB = bindings::ColorspaceType_HWBColorspace, + Lab = bindings::ColorspaceType_LabColorspace, + LCH = bindings::ColorspaceType_LCHColorspace, + LCHab = bindings::ColorspaceType_LCHabColorspace, + LCHuv = bindings::ColorspaceType_LCHuvColorspace, + Log = bindings::ColorspaceType_LogColorspace, + LMS = bindings::ColorspaceType_LMSColorspace, + Luv = bindings::ColorspaceType_LuvColorspace, + OHTA = bindings::ColorspaceType_OHTAColorspace, + Rec601YCbCr = bindings::ColorspaceType_Rec601YCbCrColorspace, + Rec709YCbCr = bindings::ColorspaceType_Rec709YCbCrColorspace, + RGB = bindings::ColorspaceType_RGBColorspace, + scRGB = bindings::ColorspaceType_scRGBColorspace, + sRGB = bindings::ColorspaceType_sRGBColorspace, + Transparent = bindings::ColorspaceType_TransparentColorspace, + xyY = bindings::ColorspaceType_xyYColorspace, + XYZ = bindings::ColorspaceType_XYZColorspace, + YCbCr = bindings::ColorspaceType_YCbCrColorspace, + YCC = bindings::ColorspaceType_YCCColorspace, + YDbDr = bindings::ColorspaceType_YDbDrColorspace, + YIQ = bindings::ColorspaceType_YIQColorspace, + YPbPr = bindings::ColorspaceType_YPbPrColorspace, + YUV = bindings::ColorspaceType_YUVColorspace, + LinearGRAY = bindings::ColorspaceType_LinearGRAYColorspace, + Jzazbz = bindings::ColorspaceType_JzazbzColorspace, + DisplayP3 = bindings::ColorspaceType_DisplayP3Colorspace, + Adobe98 = bindings::ColorspaceType_Adobe98Colorspace, + ProPhoto = bindings::ColorspaceType_ProPhotoColorspace, + Oklab = bindings::ColorspaceType_OklabColorspace, + Oklch = bindings::ColorspaceType_OklchColorspace, +} + +impl Default for ColorspaceType { + fn default() -> Self { + return ColorspaceType::RGB; + } +} + +impl From for bindings::ColorspaceType { + fn from(value: ColorspaceType) -> Self { + return value as bindings::ColorspaceType; + } +} + +impl From for ColorspaceType { + fn from(value: bindings::ColorspaceType) -> Self { + /* + * SAFETY: + * + * `ColorspaceType` has the same repr as `bindings::ColorspaceType` - u32 + * + * If `value` is less than Oklch than it is in the vaild range and can be safely + * reinterpreted as `ColorspaceType` + */ + if value <= bindings::ColorspaceType_OklchColorspace { + return unsafe { std::mem::transmute(value) }; + } + return ColorspaceType::default(); + } +} diff --git a/src/types/mod.rs b/src/types/mod.rs index 3891ff1..ce1fe30 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -1,7 +1,9 @@ +mod colorspace_type; mod composite_operator; mod metric_type; mod resource_type; +pub use self::colorspace_type::ColorspaceType; pub use self::composite_operator::CompositeOperator; pub use self::metric_type::MetricType; pub use self::resource_type::ResourceType; diff --git a/src/types/resource_type.rs b/src/types/resource_type.rs index e31499c..45467a5 100644 --- a/src/types/resource_type.rs +++ b/src/types/resource_type.rs @@ -3,7 +3,7 @@ use std::convert::TryInto; use crate::bindings; /// Resource type to use with [set_resource_limit](crate::MagickWand::set_resource_limit) -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ResourceType { Undefined = bindings::ResourceType_UndefinedResource as isize, Area = bindings::ResourceType_AreaResource as isize, diff --git a/src/wand/magick.rs b/src/wand/magick.rs index 007fbe9..8f8533a 100644 --- a/src/wand/magick.rs +++ b/src/wand/magick.rs @@ -29,7 +29,12 @@ use {size_t, ssize_t}; use crate::result::Result; use super::{DrawingWand, PixelWand}; -use crate::{CompositeOperator, MetricType, ResourceType}; +use crate::{ + ColorspaceType, + CompositeOperator, + MetricType, + ResourceType +}; wand_common!( MagickWand, @@ -1086,12 +1091,78 @@ impl MagickWand { } } - mutations!( - /// Set the image colorspace, transforming (unlike `set_image_colorspace`) image data in - /// the process. - MagickTransformImageColorspace => transform_image_colorspace( - colorspace: bindings::ColorspaceType) + /// Set the image colorspace, transforming (unlike `set_image_colorspace`) image data in + /// the process. + pub fn transform_image_colorspace(&self, colorspace: ColorspaceType) -> Result<()> { + match unsafe { bindings::MagickTransformImageColorspace(self.wand, colorspace.into()) } { + bindings::MagickBooleanType_MagickTrue => Ok(()), + _ => Err(MagickError("failed to transform image colorspace")), + } + } + /// Reduce the number of colors in the image. + pub fn quantize_image( + &self, + number_of_colors: size_t, + colorspace: ColorspaceType, + tree_depth: size_t, + dither_method: bindings::DitherMethod, + measure_error: bool) -> Result<()> { + match unsafe { bindings::MagickQuantizeImage( + self.wand, + number_of_colors, + colorspace.into(), + tree_depth, + dither_method, + measure_error.to_magick()) } { + bindings::MagickBooleanType_MagickTrue => Ok(()), + _ => Err(MagickError("failed to quantize image")), + } + } + + /// Reduce the number of colors in the images. + pub fn quantize_images( + &self, + number_of_colors: size_t, + colorspace: ColorspaceType, + tree_depth: size_t, + dither_method: bindings::DitherMethod, + measure_error: bool) -> Result<()> { + match unsafe { bindings::MagickQuantizeImages( + self.wand, + number_of_colors, + colorspace.into(), + tree_depth, + dither_method, + measure_error.to_magick()) } { + bindings::MagickBooleanType_MagickTrue => Ok(()), + _ => Err(MagickError("failed to quantize images")), + } + } + + pub fn get_colorspace(&self) -> ColorspaceType { + return unsafe { bindings::MagickGetColorspace(self.wand).into() }; + } + + pub fn set_colorspace(&mut self, colorspace: ColorspaceType) -> Result<()> { + match unsafe { bindings::MagickSetColorspace(self.wand, colorspace.into()) } { + bindings::MagickBooleanType_MagickTrue => Ok(()), + _ => Err(MagickError("failed to set colorspace")), + } + } + + pub fn get_image_colorspace(&self) -> ColorspaceType { + return unsafe { bindings::MagickGetImageColorspace(self.wand).into() }; + } + + pub fn set_image_colorspace(&self, colorspace: ColorspaceType) -> Result<()> { + match unsafe { bindings::MagickSetImageColorspace(self.wand, colorspace.into()) } { + bindings::MagickBooleanType_MagickTrue => Ok(()), + _ => Err(MagickError("failed to set image colorspace")), + } + } + + mutations!( /// Sets the image to the specified alpha level. MagickSetImageAlpha => set_image_alpha(alpha: f64) @@ -1105,16 +1176,6 @@ impl MagickWand { MagickSetImageAlphaChannel => set_image_alpha_channel( alpha_channel: bindings::AlphaChannelOption) - /// Reduce the number of colors in the image. - MagickQuantizeImage => quantize_image( - number_of_colors: size_t, colorspace: bindings::ColorspaceType, - tree_depth: size_t, dither_method: bindings::DitherMethod, measure_error: bindings::MagickBooleanType) - - /// Reduce the number of colors in the image. - MagickQuantizeImages => quantize_images( - number_of_colors: size_t, colorspace: bindings::ColorspaceType, - tree_depth: size_t, dither_method: bindings::DitherMethod, measure_error: bindings::MagickBooleanType) - /// Discard all but one of any pixel color. MagickUniqueImageColors => unique_image_colors() @@ -1139,11 +1200,9 @@ impl MagickWand { ); set_get!( - get_colorspace, set_colorspace, MagickGetColorspace, MagickSetColorspace, bindings::ColorspaceType get_compression, set_compression, MagickGetCompression, MagickSetCompression, bindings::CompressionType get_compression_quality, set_compression_quality, MagickGetCompressionQuality, MagickSetCompressionQuality, size_t get_gravity, set_gravity, MagickGetGravity, MagickSetGravity, bindings::GravityType - get_image_colorspace, set_image_colorspace, MagickGetImageColorspace, MagickSetImageColorspace, bindings::ColorspaceType get_image_compression, set_image_compression, MagickGetImageCompression, MagickSetImageCompression, bindings::CompressionType get_image_compression_quality, set_image_compression_quality, MagickGetImageCompressionQuality, MagickSetImageCompressionQuality, size_t get_image_delay, set_image_delay, MagickGetImageDelay, MagickSetImageDelay, size_t diff --git a/tests/lib.rs b/tests/lib.rs index 1e12294..4c3824e 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -250,18 +250,18 @@ fn test_transform_image_colorspace() { assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok()); assert_eq!( wand.get_image_colorspace(), - bindings::ColorspaceType_sRGBColorspace + magick_rust::ColorspaceType::sRGB ); let pixel_color = wand.get_image_pixel_color(10, 10).unwrap(); assert_ne!(pixel_color.get_hsl().hue, 0.0); assert!(wand - .transform_image_colorspace(bindings::ColorspaceType_GRAYColorspace) + .transform_image_colorspace(magick_rust::ColorspaceType::GRAY) .is_ok()); assert_eq!( wand.get_image_colorspace(), - bindings::ColorspaceType_GRAYColorspace + magick_rust::ColorspaceType::GRAY ); let pixel_grayscale = wand.get_image_pixel_color(10, 10).unwrap(); @@ -290,10 +290,10 @@ fn test_color_reduction() { assert!(wand .quantize_image( 6, - bindings::ColorspaceType_RGBColorspace, + magick_rust::ColorspaceType::RGB, 1, bindings::DitherMethod_UndefinedDitherMethod, - false.to_magick() + false ) .is_ok()); assert_eq!(6, wand.get_image_colors());